diff --git a/ChangeLog b/ChangeLog index ccc83b574..7421e102f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,7 @@ Easy-RSA 3 ChangeLog 3.2.0 (TBD) + * Remove EASYRSA_NO_VARS; Allow graceful use without a vars file (#1043) * New diagnostic command 'display-cn' (#1040) * Expand renewable certificate types to include code-signing (#1039) diff --git a/easyrsa3/easyrsa b/easyrsa3/easyrsa index 7739b871b..cd88572d4 100755 --- a/easyrsa3/easyrsa +++ b/easyrsa3/easyrsa @@ -698,18 +698,24 @@ Type the word '$value' to continue, or any other input to abort." # Cannot use easyrsa-openssl() due to chicken vs egg, # easyrsa_openssl() creates temp-files, # which needs `openssl rand`. -# Redirect error-out, ignore complaints of missing config easyrsa_random() { case "$1" in - (*[!1234567890]*|0*|"") : ;; # invalid input - (*) - # Only return on success - if OPENSSL_CONF=/dev/null \ - "$EASYRSA_OPENSSL" rand -hex "$1" - then - return - fi + *[!1234567890]*|0*|"") + die "easyrsa_random - input" esac + + unset -v rand_hex + if rand_hex="$( + OPENSSL_CONF=/dev/null \ + "$EASYRSA_OPENSSL" rand -hex "$1" + )" + then + if [ "$2" ]; then + force_set_var "$2" "$rand_hex" + fi + return + fi + die "easyrsa_random failed" } # => easyrsa_random() @@ -729,10 +735,9 @@ secure_session() { * $EASYRSA_TEMP_DIR" fi + session= for i in 1 2 3; do - session="$( - easyrsa_random 4 - )" || die "secure_session - session" + easyrsa_random 4 session secured_session="${EASYRSA_TEMP_DIR}/${session}" # atomic: @@ -1516,14 +1521,20 @@ get_passphrase() { # build-ca backend: build_ca() { cipher="-aes256" - unset -v sub_ca ssl_batch date_stamp x509 error_info + unset -v sub_ca ssl_batch date_stamp x509 error_info \ + ca_password_via_cmdline + while [ "$1" ]; do case "$1" in - intca|subca) sub_ca=1 ;; + intca|subca) + sub_ca=1 + ;; nopass) [ "$prohibit_no_pass" ] || EASYRSA_NO_PASS=1 ;; - raw-ca|raw) EASYRSA_RAW_CA=1 ;; + raw-ca|raw) + EASYRSA_RAW_CA=1 + ;; *) warn "Ignoring unknown command option: '$1'" esac shift @@ -1654,9 +1665,10 @@ Raw CA mode elif [ "$EASYRSA_PASSOUT" ] && [ "$EASYRSA_PASSIN" ] then - : # passphrase defined + # passphrase defined on command line # Both --passout and --passin # must be defined for a CA with a password + ca_password_via_cmdline=1 else # Assign passphrase vars @@ -1693,9 +1705,9 @@ Raw CA mode fi # Assign tmp-file for config - raw_ssl_cnf_tmp="" - easyrsa_mktemp raw_ssl_cnf_tmp || \ - die "build_ca - easyrsa_mktemp raw_ssl_cnf_tmp" + adjusted_ssl_cnf_tmp="" + easyrsa_mktemp adjusted_ssl_cnf_tmp || \ + die "build_ca - easyrsa_mktemp adjusted_ssl_cnf_tmp" # Assign awkscript to insert EASYRSA_EXTRA_EXTS # shellcheck disable=SC2016 # vars don't expand in '' @@ -1705,151 +1717,109 @@ Raw CA mode {print} }' + # Find or create x509 CA file + if [ -f "$EASYRSA_EXT_DIR/ca" ]; then + # Use the x509-types/ca file + x509_ca_file="$EASYRSA_EXT_DIR/ca" + else + # Use a temp file + write_x509_type_tmp ca + x509_ca_file="$x509_tmp" + fi + + # Find or create x509 COMMON file + if [ -f "$EASYRSA_EXT_DIR/COMMON" ]; then + # Use the x509-types/COMMON file + x509_COMMON_file="$EASYRSA_EXT_DIR/COMMON" + else + # Use a temp file + write_x509_type_tmp COMMON + x509_COMMON_file="$x509_tmp" + fi + # Insert x509-types COMMON and 'ca' and EASYRSA_EXTRA_EXTS { - # 'ca' file - if [ -f "$EASYRSA_EXT_DIR/ca" ]; then - cat "$EASYRSA_EXT_DIR/ca" - else - create_x509_type ca - fi - - # COMMON file - if [ -f "$EASYRSA_EXT_DIR/COMMON" ]; then - cat "$EASYRSA_EXT_DIR/COMMON" - else - create_x509_type COMMON - fi + # X509 files + cat "$x509_ca_file" "$x509_COMMON_file" # User extentions [ "$EASYRSA_EXTRA_EXTS" ] && \ print "$EASYRSA_EXTRA_EXTS" } | awk "$awkscript" "$EASYRSA_SSL_CONF" \ - > "$raw_ssl_cnf_tmp" || \ - die "Copying X509_TYPES to config file failed" + > "$adjusted_ssl_cnf_tmp" || \ + die "Copying X509_TYPES to config file failed" verbose "build-ca: insert x509 and extensions OK" # Use this new SSL config for the rest of this function - EASYRSA_SSL_CONF="$raw_ssl_cnf_tmp" + EASYRSA_SSL_CONF="$adjusted_ssl_cnf_tmp" # Generate CA Key - if [ "$EASYRSA_RAW_CA" ]; then - case "$EASYRSA_ALGO" in - rsa) - if easyrsa_openssl genpkey \ - -algorithm "$EASYRSA_ALGO" \ - -pkeyopt \ - rsa_keygen_bits:"$EASYRSA_ALGO_PARAMS" \ - -out "$out_key_tmp" \ - ${cipher:+ "$cipher"} - then - : # ok - else - die "Failed create CA private key" - fi - ;; - ec) - if easyrsa_openssl genpkey \ - -paramfile "$EASYRSA_ALGO_PARAMS" \ - -out "$out_key_tmp" \ - ${cipher:+ "$cipher"} - then - : # ok - else - die "Failed create CA private key" - fi - ;; - ed) - if easyrsa_openssl genpkey \ - -algorithm "$EASYRSA_CURVE" \ - -out "$out_key_tmp" \ - ${cipher:+ "$cipher"} - then - : # ok - else - die "Failed create CA private key" - fi - ;; - *) die "Unknown algorithm: $EASYRSA_ALGO" - esac + case "$EASYRSA_ALGO" in + rsa) + easyrsa_openssl genpkey \ + -algorithm "$EASYRSA_ALGO" \ + -pkeyopt rsa_keygen_bits:"$EASYRSA_ALGO_PARAMS" \ + -out "$out_key_tmp" \ + ${cipher:+ "$cipher"} \ + ${EASYRSA_PASSOUT:+ -pass "$EASYRSA_PASSOUT"} \ + ${out_key_pass_tmp:+ -pass file:"$out_key_pass_tmp"} \ + || die "Failed create CA private key" + ;; + ec) + easyrsa_openssl genpkey \ + -paramfile "$EASYRSA_ALGO_PARAMS" \ + -out "$out_key_tmp" \ + ${cipher:+ "$cipher"} \ + ${EASYRSA_PASSOUT:+ -pass "$EASYRSA_PASSOUT"} \ + ${out_key_pass_tmp:+ -pass file:"$out_key_pass_tmp"} \ + || die "Failed create CA private key" + ;; + ed) + easyrsa_openssl genpkey \ + -algorithm "$EASYRSA_CURVE" \ + -out "$out_key_tmp" \ + ${cipher:+ "$cipher"} \ + ${EASYRSA_PASSOUT:+ -pass "$EASYRSA_PASSOUT"} \ + ${out_key_pass_tmp:+ -pass file:"$out_key_pass_tmp"} \ + || die "Failed create CA private key" + ;; + *) die "Unknown algorithm: $EASYRSA_ALGO" + esac + # verbose notice + if [ "$EASYRSA_RAW_CA" ]; then verbose "\ build_ca: CA key password created via RAW" - else - case "$EASYRSA_ALGO" in - rsa) - easyrsa_openssl genpkey \ - -algorithm "$EASYRSA_ALGO" \ - -pkeyopt rsa_keygen_bits:"$EASYRSA_ALGO_PARAMS" \ - -out "$out_key_tmp" \ - ${cipher:+ "$cipher"} \ - ${EASYRSA_PASSOUT:+ -pass "$EASYRSA_PASSOUT"} \ - ${out_key_pass_tmp:+ -pass file:"$out_key_pass_tmp"} \ - || die "Failed create CA private key" - ;; - ec) - easyrsa_openssl genpkey \ - -paramfile "$EASYRSA_ALGO_PARAMS" \ - -out "$out_key_tmp" \ - ${cipher:+ "$cipher"} \ - ${EASYRSA_PASSOUT:+ -pass "$EASYRSA_PASSOUT"} \ - ${out_key_pass_tmp:+ -pass file:"$out_key_pass_tmp"} \ - || die "Failed create CA private key" - ;; - ed) - easyrsa_openssl genpkey \ - -algorithm "$EASYRSA_CURVE" \ - -out "$out_key_tmp" \ - ${cipher:+ "$cipher"} \ - ${EASYRSA_PASSOUT:+ -pass "$EASYRSA_PASSOUT"} \ - ${out_key_pass_tmp:+ -pass file:"$out_key_pass_tmp"} \ - || die "Failed create CA private key" - ;; - *) die "Unknown algorithm: $EASYRSA_ALGO" - esac - - [ "$EASYRSA_NO_PASS" ] || verbose "\ + if [ "$ca_password_via_cmdline" ]; then + verbose "\ +build_ca: CA key password created via command options" + else + if [ "$EASYRSA_NO_PASS" ]; then + verbose "\ +build_ca: CA key has no password" + else + verbose "\ build_ca: CA key password created via temp-files" + fi + fi fi # Generate the CA keypair: - if [ "$EASYRSA_RAW_CA" ]; then - if easyrsa_openssl req -utf8 -new \ - -key "$out_key_tmp" \ - -out "$out_file_tmp" \ - ${x509:+ -x509} \ - ${date_stamp:+ -days "$EASYRSA_CA_EXPIRE"} \ - ${EASYRSA_DIGEST:+ -"$EASYRSA_DIGEST"} - then - : # ok - unset -v error_info - else - die "Failed to build the CA keypair." - fi - - verbose "\ -build_ca: CA certificate password created via RAW" - - else - easyrsa_openssl req -utf8 -new \ - -key "$out_key_tmp" -keyout "$out_key_tmp" \ - -out "$out_file_tmp" \ - ${ssl_batch:+ -batch} \ - ${x509:+ -x509} \ - ${date_stamp:+ -days "$EASYRSA_CA_EXPIRE"} \ - ${EASYRSA_DIGEST:+ -"$EASYRSA_DIGEST"} \ - ${EASYRSA_NO_PASS:+ "$no_password"} \ - ${EASYRSA_PASSIN:+ -passin "$EASYRSA_PASSIN"} \ - ${EASYRSA_PASSOUT:+ -passout "$EASYRSA_PASSOUT"} \ - ${in_key_pass_tmp:+ -passin file:"$in_key_pass_tmp"} \ - ${out_key_pass_tmp:+ -passout file:"$out_key_pass_tmp"} \ - || die "Failed to build the CA keypair" - - [ "$EASYRSA_NO_PASS" ] || verbose "\ -build_ca: CA certificate password created via temp-files" - fi + easyrsa_openssl req -utf8 -new \ + -key "$out_key_tmp" -keyout "$out_key_tmp" \ + -out "$out_file_tmp" \ + ${ssl_batch:+ -batch} \ + ${x509:+ -x509} \ + ${date_stamp:+ -days "$EASYRSA_CA_EXPIRE"} \ + ${EASYRSA_DIGEST:+ -"$EASYRSA_DIGEST"} \ + ${EASYRSA_NO_PASS:+ "$no_password"} \ + ${EASYRSA_PASSIN:+ -passin "$EASYRSA_PASSIN"} \ + ${EASYRSA_PASSOUT:+ -passout "$EASYRSA_PASSOUT"} \ + ${in_key_pass_tmp:+ -passin file:"$in_key_pass_tmp"} \ + ${out_key_pass_tmp:+ -passout file:"$out_key_pass_tmp"} \ + || die "Failed to build the CA keypair" # Move temp-files to target-files mv "$out_key_tmp" "$out_key" || mv_temp_error=1 @@ -1963,12 +1933,16 @@ Run easyrsa without commands for usage and commands." # function opts support while [ "$1" ]; do case "$1" in - text) text=1 ;; + text) + text=1 + ;; nopass) [ "$prohibit_no_pass" ] || EASYRSA_NO_PASS=1 ;; # batch flag supports internal caller build_full() - batch) ssl_batch=1 ;; + batch) + ssl_batch=1 + ;; *) warn "Ignoring unknown command option: '$1'" esac shift @@ -2012,18 +1986,18 @@ $EASYRSA_EXTRA_EXTS" {print} }' # Assign temp-file for confg - raw_ssl_cnf_tmp="" - easyrsa_mktemp raw_ssl_cnf_tmp || \ - die "gen_req - easyrsa_mktemp raw_ssl_cnf_tmp" + adjusted_ssl_cnf_tmp="" + easyrsa_mktemp adjusted_ssl_cnf_tmp || \ + die "gen_req - easyrsa_mktemp adjusted_ssl_cnf_tmp" # Insert $extra_exts @ %EXTRA_EXTS% in SSL Config print "$extra_exts" | \ awk "$awkscript" "$EASYRSA_SSL_CONF" \ - > "$raw_ssl_cnf_tmp" || \ + > "$adjusted_ssl_cnf_tmp" || \ die "Writing SSL config to temp file failed" # Use this SSL config for the rest of this function - EASYRSA_SSL_CONF="$raw_ssl_cnf_tmp" + EASYRSA_SSL_CONF="$adjusted_ssl_cnf_tmp" fi # Name temp files @@ -2101,8 +2075,7 @@ expected 2, got $# (see command help for usage)" preserve*) export EASYRSA_PRESERVE_DN=1 ;; - *) - warn "Ignoring unknown option '$1'" + *) warn "Ignoring unknown option '$1'" esac shift done @@ -2134,9 +2107,7 @@ The certificate request file is not in a valid X509 format: check_serial="" unset -v serial_is_unique for i in 1 2 3 4 5; do - serial="$( - easyrsa_random 16 - )" || die "sign_req - easyrsa_random" + easyrsa_random 4 serial # Check for duplicate serial in CA db if check_serial_unique "$serial" batch; then @@ -2183,17 +2154,17 @@ to the latest Easy-RSA release." {print} }' # Assign temp-file for confg - raw_ssl_cnf_tmp="" - easyrsa_mktemp raw_ssl_cnf_tmp || \ - die "sign_req - easyrsa_mktemp raw_ssl_cnf_tmp" + adjusted_ssl_cnf_tmp="" + easyrsa_mktemp adjusted_ssl_cnf_tmp || \ + die "sign_req - easyrsa_mktemp adjusted_ssl_cnf_tmp" print "$copy_exts" | \ awk "$awkscript" "$EASYRSA_SSL_CONF" \ - > "$raw_ssl_cnf_tmp" || die "\ + > "$adjusted_ssl_cnf_tmp" || die "\ Writing 'copy_exts' to SSL config temp-file failed" # Use this SSL config for the rest of this function - EASYRSA_SSL_CONF="$raw_ssl_cnf_tmp" + EASYRSA_SSL_CONF="$adjusted_ssl_cnf_tmp" verbose "sign_req: Using '$copy_exts'" fi @@ -2203,14 +2174,8 @@ Writing 'copy_exts' to SSL config temp-file failed" x509_type_file="$EASYRSA_EXT_DIR/$crt_type" else # Use a temp file - x509_type_tmp="" - easyrsa_mktemp x509_type_tmp || \ - die "sign_req - easyrsa_mktemp x509_type_tmp" - - create_x509_type "$crt_type" > "$x509_type_tmp" || \ - die "sign_req - create_x509_type $crt_type" - - x509_type_file="$x509_type_tmp" + write_x509_type_tmp "$crt_type" + x509_type_file="$x509_tmp" fi # Find or create x509 COMMON file @@ -2219,14 +2184,8 @@ Writing 'copy_exts' to SSL config temp-file failed" x509_COMMON_file="$EASYRSA_EXT_DIR/COMMON" else # Use a temp file - x509_COMMON_tmp="" - easyrsa_mktemp x509_COMMON_tmp || \ - die "sign_req - easyrsa_mktemp x509_COMMON_tmp" - - create_x509_type COMMON > "$x509_COMMON_tmp" || \ - die "sign_req - create_x509_type COMMON" - - x509_COMMON_file="$x509_COMMON_tmp" + write_x509_type_tmp COMMON + x509_COMMON_file="$x509_tmp" fi # Support a dynamic CA path length when present: @@ -2249,7 +2208,7 @@ basicConstraints is not defined, cannot use 'pathlen'" # Deprecated Netscape extension support case "$EASYRSA_NS_SUPPORT" in - [yY][eE][sS]) + [yY][eE][sS]) confirm "Confirm use of Netscape extensions: " yes \ "WARNING: Netscape extensions are DEPRECATED!" @@ -2398,9 +2357,6 @@ check_serial_unique() { case "$1" in (*[!1234567890abcdef]*) user_error "Invalid serial number: '$1'" - ;; - *) - : # ok esac unset -v unique_serial_true @@ -3696,7 +3652,7 @@ Expected to find the request at: verify_file req "$in_req" || user_error "\ The certificate request file is not in a valid X509 format: -* $req_in" +* $in_req" # destination must not exist [ -e "$out_req" ] && user_error "\ @@ -3958,7 +3914,9 @@ Run easyrsa without commands for usage and command help." nopass) [ "$prohibit_no_pass" ] || EASYRSA_NO_PASS=1 ;; - file) file="$raw_file" ;; + file) + file="$raw_file" + ;; *) warn "Ignoring unknown command option: '$1'" esac shift @@ -4026,7 +3984,9 @@ Missing argument: no name/file supplied." nopass) [ "$prohibit_no_pass" ] || EASYRSA_NO_PASS=1 ;; - file) file="$raw_file" ;; + file) + file="$raw_file" + ;; *) warn "Ignoring unknown command option: '$1'" esac shift @@ -5432,52 +5392,6 @@ before they can be revoked." } # => status() -# set_var is not known by shellcheck, therefore: -# Fake declare known variables for shellcheck -# Use these options without this function: -# -o all -e 2250,2244,2248 easyrsa -# shellcheck disable=2317 # Unreachable code .. -satisfy_shellcheck() { - die "Security feature enabled!" - # Add more as/if required - - # Enable the heredoc for a peek -#cat << SC2154 - EASYRSA= - EASYRSA_OPENSSL= - EASYRSA_PKI= - EASYRSA_DN= - EASYRSA_REQ_COUNTRY= - EASYRSA_REQ_PROVINCE= - EASYRSA_REQ_CITY= - EASYRSA_REQ_ORG= - EASYRSA_REQ_EMAIL= - EASYRSA_REQ_OU= - EASYRSA_ALGO= - EASYRSA_KEY_SIZE= - EASYRSA_CURVE= - EASYRSA_CA_EXPIRE= - EASYRSA_CERT_EXPIRE= - EASYRSA_PRE_EXPIRY_WINDOW= - EASYRSA_CRL_DAYS= - EASYRSA_NS_SUPPORT= - EASYRSA_NS_COMMENT= - EASYRSA_TEMP_DIR= - EASYRSA_REQ_CN= - EASYRSA_DIGEST= - - EASYRSA_SSL_CONF= - EASYRSA_SAFE_CONF= - OPENSSL_CONF= - - #EASYRSA_KDC_REALM= - - EASYRSA_RAND_SN= - KSH_VERSION= -#SC2154 - -} # => satisfy_shellcheck() - # Identify host OS detect_host() { unset -v \ @@ -5647,15 +5561,8 @@ To correct this problem, it is recommended that you either: # If not present, defaults are used to support # running without a sourced config format. select_vars() { - # No vars file will be used - if [ "$EASYRSA_NO_VARS" ]; then - verbose "select_vars: EASYRSA_NO_VARS" - unset -v EASYRSA_VARS_FILE - # skip the rest of this function - return - # User specified vars file will be used ONLY - elif [ "$EASYRSA_VARS_FILE" ]; then + if [ "$EASYRSA_VARS_FILE" ]; then # Takes priority, nothing to do verbose "select_vars: EASYRSA_VARS_FILE" @@ -5713,7 +5620,8 @@ select_vars() { if [ -z "$EASYRSA_VARS_FILE" ]; then [ "$require_pki" ] && information "\ No Easy-RSA 'vars' configuration file exists!" - EASYRSA_NO_VARS=1 + # select_vars failed to find a vars file + return 1 fi } # => select_vars() @@ -5935,46 +5843,37 @@ verify_working_env() { # Verify PKI is initialised verify_pki_init - # Temp dir MUST exist - if [ -d "$EASYRSA_TEMP_DIR" ]; then - - # Temp dir session - secure_session || die "\ + # Temp dir session + secure_session || die "\ verify_working_env - secure-session failed" - # Install data-files into ALL PKIs - # This will find x509-types - # and export EASYRSA_EXT_DIR or die. - # Other errors only require warning. - install_data_to_pki vars-setup || warn "\ + # Install data-files into ALL PKIs + # This will find x509-types + # and export EASYRSA_EXT_DIR or die. + # Other errors only require warning. + install_data_to_pki vars-setup || warn "\ verify_working_env - install_data_to_pki vars-setup failed" - # Verify selected algorithm and parameters - verify_algo_params + # Verify selected algorithm and parameters + verify_algo_params - # Check $working_safe_ssl_conf, to build - # a fully configured safe ssl conf, on the - # next invocation of easyrsa_openssl() - if [ "$working_safe_ssl_conf" ]; then - die "working_safe_ssl_conf must not be set!" - fi + # Check $working_safe_ssl_conf, to build + # a fully configured safe ssl conf, on the + # next invocation of easyrsa_openssl() + if [ "$working_safe_ssl_conf" ]; then + die "working_safe_ssl_conf must not be set!" + fi - # Verify CA is initialised - if [ "$require_ca" ]; then - verify_ca_init - fi + # Verify CA is initialised + if [ "$require_ca" ]; then + verify_ca_init + fi - # Last setup msg - information " + # Last setup msg + information " Using SSL: * $EASYRSA_OPENSSL $ssl_version" - else - # The directory does not exist - user_error "\ -Temporary directory does not exist: -* $EASYRSA_TEMP_DIR" - fi fi verbose "verify_working_env: COMPLETED Handover-to: $cmd" } # => verify_working_env() @@ -6017,6 +5916,24 @@ force_set_var() { ############################################################################ # # Create X509-type files + +# Write x509 type file to a temp file +write_x509_type_tmp() { + # Use a temp file + type="$1" + shift + + x509_tmp="" + easyrsa_mktemp x509_tmp || \ + die "write_x509_type_tmp - easyrsa_mktemp x509_tmp" + + create_x509_type "$type" > "$x509_tmp" || \ + die "write_x509_type_tmp - create_x509_type $type" + + verbose "write_x509_type_tmp: $type COMPLETE" +} # => write_x509_type_tmp() + +# Create x509 type create_x509_type() { case "$1" in COMMON) @@ -7265,10 +7182,9 @@ esac # Intelligent env-var detection and auto-loading: # Select vars file as EASYRSA_VARS_FILE -select_vars - -# source the vars file -[ "$EASYRSA_NO_VARS" ] || source_vars "$EASYRSA_VARS_FILE" +# then source the vars file, if found +# otherwise, ignore no vars file +select_vars && source_vars "$EASYRSA_VARS_FILE" # then set defaults default_vars