2580 lines
		
	
	
		
			75 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			2580 lines
		
	
	
		
			75 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
#!/bin/sh
 | 
						|
 | 
						|
# Easy-RSA 3 -- A Shell-based CA Utility
 | 
						|
#
 | 
						|
# Copyright (C) 2018 by the Open-Source OpenVPN development community.
 | 
						|
# A full list of contributors can be found in the ChangeLog.
 | 
						|
#
 | 
						|
# This code released under version 2 of the GNU GPL; see COPYING and the
 | 
						|
# Licensing/ directory of this project for full licensing details.
 | 
						|
 | 
						|
# Help/usage output to stdout
 | 
						|
usage() {
 | 
						|
	# command help:
 | 
						|
	print "
 | 
						|
Easy-RSA 3 usage and overview
 | 
						|
 | 
						|
USAGE: easyrsa [options] COMMAND [command-options]
 | 
						|
 | 
						|
A list of commands is shown below. To get detailed usage and help for a
 | 
						|
command, run:
 | 
						|
  ./easyrsa help COMMAND
 | 
						|
 | 
						|
For a listing of options that can be supplied before the command, use:
 | 
						|
  ./easyrsa help options
 | 
						|
 | 
						|
Here is the list of commands available with a short syntax reminder. Use the
 | 
						|
'help' command above to get full usage details.
 | 
						|
 | 
						|
  init-pki
 | 
						|
  build-ca [ cmd-opts ]
 | 
						|
  gen-dh
 | 
						|
  gen-req <filename_base> [ cmd-opts ]
 | 
						|
  sign-req <type> <filename_base>
 | 
						|
  build-client-full <filename_base> [ cmd-opts ]
 | 
						|
  build-server-full <filename_base> [ cmd-opts ]
 | 
						|
  revoke <filename_base> [cmd-opts]
 | 
						|
  renew <filename_base> [cmd-opts]
 | 
						|
  build-serverClient-full <filename_base> [ cmd-opts ]
 | 
						|
  gen-crl
 | 
						|
  update-db
 | 
						|
  show-req <filename_base> [ cmd-opts ]
 | 
						|
  show-cert <filename_base> [ cmd-opts ]
 | 
						|
  show-ca [ cmd-opts ]
 | 
						|
  import-req <request_file_path> <short_basename>
 | 
						|
  export-p7 <filename_base> [ cmd-opts ]
 | 
						|
  export-p8 <filename_base> [ cmd-opts ]
 | 
						|
  export-p12 <filename_base> [ cmd-opts ]
 | 
						|
  set-rsa-pass <filename_base> [ cmd-opts ]
 | 
						|
  set-ec-pass <filename_base> [ cmd-opts ]
 | 
						|
  upgrade <type>
 | 
						|
"
 | 
						|
 | 
						|
	# collect/show dir status:
 | 
						|
	err_source="Not defined: vars autodetect failed and no value provided"
 | 
						|
	work_dir="${EASYRSA:-$err_source}"
 | 
						|
	pki_dir="${EASYRSA_PKI:-$err_source}"
 | 
						|
	print "\
 | 
						|
DIRECTORY STATUS (commands would take effect on these locations)
 | 
						|
  EASYRSA: $work_dir
 | 
						|
      PKI: $pki_dir
 | 
						|
"
 | 
						|
} # => usage()
 | 
						|
 | 
						|
# Detailed command help
 | 
						|
# When called with no args, calls usage(), otherwise shows help for a command
 | 
						|
cmd_help() {
 | 
						|
	text=""
 | 
						|
	opts=""
 | 
						|
	case "$1" in
 | 
						|
		init-pki|clean-all) text="
 | 
						|
  init-pki [ cmd-opts ]
 | 
						|
      Removes & re-initializes the PKI dir for a clean PKI" ;;
 | 
						|
		build-ca) text="
 | 
						|
  build-ca [ cmd-opts ]
 | 
						|
      Creates a new CA"
 | 
						|
      			opts="
 | 
						|
        nopass  - do not encrypt the CA key (default is encrypted)
 | 
						|
        subca   - create an intermediate CA keypair and request (default is a root CA)
 | 
						|
        intca   - alias to the above" ;;
 | 
						|
		gen-dh) text="
 | 
						|
  gen-dh
 | 
						|
      Generates DH (Diffie-Hellman) parameters" ;;
 | 
						|
		gen-req) text="
 | 
						|
  gen-req <filename_base> [ cmd-opts ]
 | 
						|
      Generate a standalone keypair and request (CSR)
 | 
						|
 | 
						|
      This request is suitable for sending to a remote CA for signing."
 | 
						|
      			opts="
 | 
						|
        nopass  - do not encrypt the private key (default is encrypted)" ;;
 | 
						|
		sign|sign-req) text="
 | 
						|
  sign-req <type> <filename_base>
 | 
						|
      Sign a certificate request of the defined type. <type> must be a known
 | 
						|
      type such as 'client', 'server', 'serverClient', or 'ca' (or a user-added type.)
 | 
						|
 | 
						|
      This request file must exist in the reqs/ dir and have a .req file
 | 
						|
      extension. See import-req below for importing reqs from other sources." ;;
 | 
						|
		build|build-client-full|build-server-full|build-serverClient-full) text="
 | 
						|
  build-client-full <filename_base> [ cmd-opts ]
 | 
						|
  build-server-full <filename_base> [ cmd-opts ]
 | 
						|
  build-serverClient-full <filename_base> [ cmd-opts ]
 | 
						|
      Generate a keypair and sign locally for a client and/or server
 | 
						|
 | 
						|
      This mode uses the <filename_base> as the X509 CN."
 | 
						|
			opts="
 | 
						|
        nopass  - do not encrypt the private key (default is encrypted)
 | 
						|
        inline  - create an inline credentials file for this node" ;;
 | 
						|
		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";;
 | 
						|
		renew) text="
 | 
						|
  renew <filename_base> [ cmd-opts ]
 | 
						|
      Renew a certificate specified by the filename_base"
 | 
						|
				opts="
 | 
						|
        nopass  - do not encrypt the private key (default is encrypted)" ;;
 | 
						|
		gen-crl) text="
 | 
						|
  gen-crl
 | 
						|
      Generate a CRL" ;;
 | 
						|
		update-db) text="
 | 
						|
  update-db
 | 
						|
      Update the index.txt database
 | 
						|
 | 
						|
      This command will use the system time to update the status of issued
 | 
						|
      certificates." ;;
 | 
						|
      		show-req|show-cert) text="
 | 
						|
  show-req  <filename_base> [ cmd-opts ]
 | 
						|
  show-cert <filename_base> [ cmd-opts ]
 | 
						|
      Shows details of the req or cert referenced by filename_base
 | 
						|
 | 
						|
      Human-readable output is shown, including any requested cert options when
 | 
						|
      showing a request."
 | 
						|
      			opts="
 | 
						|
          full   - show full req/cert info, including pubkey/sig data" ;;
 | 
						|
		show-ca) text="
 | 
						|
  show-ca [ cmd-opts ]
 | 
						|
      Shows details of the CA cert
 | 
						|
 | 
						|
      Human-readable output is shown."
 | 
						|
			opts="
 | 
						|
          full   - show full cert info, including pubkey/sig data" ;;
 | 
						|
		import-req) text="
 | 
						|
  import-req <request_file_path> <short_basename>
 | 
						|
      Import a certificate request from a file
 | 
						|
 | 
						|
      This will copy the specified file into the reqs/ dir in
 | 
						|
      preparation for signing.
 | 
						|
      The <short_basename> is the filename base to create.
 | 
						|
 | 
						|
      Example usage:
 | 
						|
        import-req /some/where/bob_request.req bob" ;;
 | 
						|
		export-p12) text="
 | 
						|
  export-p12 <filename_base> [ cmd-opts ]
 | 
						|
      Export a PKCS#12 file with the keypair specified by <filename_base>"
 | 
						|
			opts="
 | 
						|
        noca  - do not include the ca.crt file in the PKCS12 output
 | 
						|
        nokey - do not include the private key in the PKCS12 output" ;;
 | 
						|
		export-p7) text="
 | 
						|
  export-p7 <filename_base> [ cmd-opts ]
 | 
						|
      Export a PKCS#7 file with the pubkey specified by <filename_base>"
 | 
						|
			opts="
 | 
						|
        noca  - do not include the ca.crt file in the PKCS7 output" ;;
 | 
						|
		export-p8) text="
 | 
						|
  export-p8 <filename_base> [ cmd-opts ]
 | 
						|
      Export a PKCS#8 file with the private key specified by <filename_base>"
 | 
						|
			opts="
 | 
						|
        noca  - do not include the ca.crt file in the PKCS7 output" ;;
 | 
						|
		set-rsa-pass|set-ec-pass) text="
 | 
						|
  set-rsa-pass <filename_base> [ cmd-opts ]
 | 
						|
  set-ec-pass <filename_base> [ cmd-opts ]
 | 
						|
      Set a new passphrase on an RSA or EC key for the listed <filename_base>."
 | 
						|
                        opts="
 | 
						|
        nopass - use no password and leave the key unencrypted
 | 
						|
        file   - (advanced) treat the file as a raw path, not a short-name" ;;
 | 
						|
		upgrade) text="
 | 
						|
  upgrade <type>
 | 
						|
      Upgrade EasyRSA PKI and/or CA. <type> must be one of:
 | 
						|
        pki - Upgrade EasyRSA v2.x PKI to EasyRSA v3.x PKI (includes CA below)
 | 
						|
        ca  - Upgrade EasyRSA v3.0.5 CA or older to EasyRSA v3.0.6 CA or later." ;;
 | 
						|
		altname|subjectaltname|san) text="
 | 
						|
  --subject-alt-name=SAN_FORMAT_STRING
 | 
						|
      This global option adds a subjectAltName to the request or issued
 | 
						|
      certificate. It MUST be in a valid format accepted by openssl or
 | 
						|
      req/cert generation will fail. Note that including multiple such names
 | 
						|
      requires them to be comma-separated; further invocations of this
 | 
						|
      option will REPLACE the value.
 | 
						|
 | 
						|
      Examples of the SAN_FORMAT_STRING shown below:
 | 
						|
        DNS:alternate.example.net
 | 
						|
        DNS:primary.example.net,DNS:alternate.example.net
 | 
						|
        IP:203.0.113.29
 | 
						|
        email:alternate@example.net" ;;
 | 
						|
		options)
 | 
						|
			opt_usage ;;
 | 
						|
		"")
 | 
						|
			usage ;;
 | 
						|
		*) text="
 | 
						|
  Unknown command: '$1' (try without commands for a list of commands)" ;;
 | 
						|
	esac
 | 
						|
 | 
						|
	# display the help text
 | 
						|
	print "$text"
 | 
						|
	[ -n "$opts" ] && print "
 | 
						|
      cmd-opts is an optional set of command options from this list:
 | 
						|
$opts"
 | 
						|
} # => cmd_help()
 | 
						|
 | 
						|
# Options usage
 | 
						|
opt_usage() {
 | 
						|
	print "
 | 
						|
Easy-RSA Global Option Flags
 | 
						|
 | 
						|
The following options may be provided before the command. Options specified
 | 
						|
at runtime override env-vars and any 'vars' file in use. Unless noted,
 | 
						|
non-empty values to options are mandatory.
 | 
						|
 | 
						|
General options:
 | 
						|
 | 
						|
--batch         : set automatic (no-prompts when possible) mode
 | 
						|
--passin=ARG    : set -passin ARG for openssl
 | 
						|
--passout=ARG   : set -passout ARG for openssl
 | 
						|
--pki-dir=DIR   : declares the PKI directory
 | 
						|
--vars=FILE     : define a specific 'vars' file to use for Easy-RSA config
 | 
						|
--version       : prints EasyRSA version and build information, then exits
 | 
						|
 | 
						|
Certificate & Request options: (these impact cert/req field values)
 | 
						|
 | 
						|
--days=#        : sets the signing validity to the specified number of days
 | 
						|
--digest=ALG    : digest to use in the requests & certificates
 | 
						|
--dn-mode=MODE  : DN mode to use (cn_only or org)
 | 
						|
--keysize=#     : size in bits of keypair to generate
 | 
						|
--req-cn=NAME   : default CN to use
 | 
						|
--subca-len=#   : path length of signed intermediate CA certs; must be >= 0 if used
 | 
						|
--subject-alt-name : Add a subjectAltName. For more info and syntax, see:
 | 
						|
                     ./easyrsa help altname
 | 
						|
--use-algo=ALG  : crypto alg to use: choose rsa (default) or ec
 | 
						|
--curve=NAME    : for elliptic curve, sets the named curve to use
 | 
						|
--copy-ext      : Copy included request X509 extensions (namely subjAltName
 | 
						|
 | 
						|
Organizational DN options: (only used with the 'org' DN mode)
 | 
						|
  (values may be blank for org DN options)
 | 
						|
 | 
						|
--req-c=CC        : country code (2-letters)
 | 
						|
--req-st=NAME     : State/Province
 | 
						|
--req-city=NAME   : City/Locality
 | 
						|
--req-org=NAME    : Organization
 | 
						|
--req-email=NAME  : Email addresses
 | 
						|
--req-ou=NAME     : Organizational Unit
 | 
						|
 | 
						|
Deprecated features:
 | 
						|
 | 
						|
--ns-cert=YESNO       : yes or no to including deprecated NS extensions
 | 
						|
--ns-comment=COMMENT  : NS comment to include (value may be blank)
 | 
						|
"
 | 
						|
} # => opt_usage()
 | 
						|
 | 
						|
# Wrapper around printf - clobber print since it's not POSIX anyway
 | 
						|
# shellcheck disable=SC1117
 | 
						|
print() { printf "%s\n" "$*" || exit 1; }
 | 
						|
 | 
						|
# Exit fatally with a message to stderr
 | 
						|
# present even with EASYRSA_BATCH as these are fatal problems
 | 
						|
die() {
 | 
						|
	print "
 | 
						|
Easy-RSA error:
 | 
						|
 | 
						|
$1" 1>&2
 | 
						|
	exit "${2:-1}"
 | 
						|
} # => die()
 | 
						|
 | 
						|
# non-fatal warning output
 | 
						|
warn() {
 | 
						|
	[ ! "$EASYRSA_BATCH" ] && \
 | 
						|
		print "
 | 
						|
$1" 1>&2
 | 
						|
 | 
						|
	return 0
 | 
						|
} # => warn()
 | 
						|
 | 
						|
# informational notices to stdout
 | 
						|
notice() {
 | 
						|
	[ ! "$EASYRSA_BATCH" ] && \
 | 
						|
		print "
 | 
						|
$1"
 | 
						|
 | 
						|
	return 0
 | 
						|
} # => notice()
 | 
						|
 | 
						|
# yes/no case-insensitive match (operates on stdin pipe)
 | 
						|
# Returns 0 when input contains yes, 1 for no, 2 for no match
 | 
						|
# If both strings are present, returns 1; first matching line returns.
 | 
						|
awk_yesno() {
 | 
						|
	#shellcheck disable=SC2016
 | 
						|
	awkscript='
 | 
						|
BEGIN {IGNORECASE=1; r=2}
 | 
						|
{       if(match($0,"no")) {r=1; exit}
 | 
						|
        if(match($0,"yes")) {r=0; exit}
 | 
						|
} END {exit r}'
 | 
						|
	awk "$awkscript"
 | 
						|
} # => awk_yesno()
 | 
						|
 | 
						|
# intent confirmation helper func
 | 
						|
# returns without prompting in EASYRSA_BATCH
 | 
						|
confirm() {
 | 
						|
	[ "$EASYRSA_BATCH" ] && return
 | 
						|
	prompt="$1"
 | 
						|
	value="$2"
 | 
						|
	msg="$3"
 | 
						|
	input=""
 | 
						|
	print "
 | 
						|
$msg
 | 
						|
 | 
						|
Type the word '$value' to continue, or any other input to abort."
 | 
						|
	printf %s "  $prompt"
 | 
						|
	#shellcheck disable=SC2162
 | 
						|
	read input
 | 
						|
	[ "$input" = "$value" ] && return
 | 
						|
	notice "Aborting without confirmation."
 | 
						|
	exit 9
 | 
						|
} # => confirm()
 | 
						|
 | 
						|
# mktemp wrapper
 | 
						|
easyrsa_mktemp() {
 | 
						|
	[ -n "$EASYRSA_TEMP_DIR_session" ] || die "EASYRSA_TEMP_DIR_session not initialized!"
 | 
						|
	[ -d "$EASYRSA_TEMP_DIR_session" ] || mkdir -p "$EASYRSA_TEMP_DIR_session" ||
 | 
						|
	       die "Could not create temporary directory '$EASYRSA_TEMP_DIR_session'. Permission or concurrency problem?"
 | 
						|
	[ -d "$EASYRSA_TEMP_DIR_session" ] || die "Temporary directory '$EASYRSA_TEMP_DIR_session' does not exist"
 | 
						|
 | 
						|
	template="$EASYRSA_TEMP_DIR_session/tmp.XXXXXX"
 | 
						|
	tempfile=$(mktemp "$template") || return
 | 
						|
 | 
						|
	# win32 mktemp shipped by easyrsa returns template as file!
 | 
						|
	if [ "$template" = "$tempfile" ]; then
 | 
						|
		# but win32 mktemp -d does work
 | 
						|
		# but win32 mktemp -u does not work
 | 
						|
		tempfile=$(mktemp -du "$tempfile") || return
 | 
						|
		printf "" > "$tempfile" || return
 | 
						|
	fi
 | 
						|
	echo "$tempfile"
 | 
						|
} # => easyrsa_mktemp
 | 
						|
 | 
						|
# remove temp files and do terminal cleanups
 | 
						|
cleanup() {
 | 
						|
	[ -z "$EASYRSA_TEMP_DIR_session" ] || rm -rf "$EASYRSA_TEMP_DIR_session"
 | 
						|
	# shellcheck disable=SC2039
 | 
						|
	(stty echo 2>/dev/null) || { (set -o echo 2>/dev/null) && set -o echo; }
 | 
						|
	echo "" # just to get a clean line
 | 
						|
} # => cleanup()
 | 
						|
 | 
						|
easyrsa_openssl() {
 | 
						|
	openssl_command=$1; shift
 | 
						|
 | 
						|
	case $openssl_command in
 | 
						|
		makesafeconf) has_config=true;;
 | 
						|
		ca|req|srp|ts) has_config=true;;
 | 
						|
		*) has_config=false;;
 | 
						|
	esac
 | 
						|
 | 
						|
	if ! $has_config; then
 | 
						|
		"$EASYRSA_OPENSSL" "$openssl_command" "$@"
 | 
						|
		return
 | 
						|
	fi
 | 
						|
 | 
						|
	easyrsa_openssl_conf=$(easyrsa_mktemp) || die "Failed to create temporary file"
 | 
						|
	easyrsa_extra_exts=
 | 
						|
	if [ -n "$EASYRSA_EXTRA_EXTS" ]; then
 | 
						|
		easyrsa_extra_exts=$(easyrsa_mktemp) || die "Failed to create temporary file"
 | 
						|
		cat >"$easyrsa_extra_exts" <<-EOF
 | 
						|
			req_extensions = req_extra
 | 
						|
			[ req_extra ]
 | 
						|
			$EASYRSA_EXTRA_EXTS
 | 
						|
		EOF
 | 
						|
	fi
 | 
						|
 | 
						|
	# Make LibreSSL safe config file from OpenSSL config file
 | 
						|
	sed \
 | 
						|
		-e "s\`ENV::EASYRSA\`EASYRSA\`g" \
 | 
						|
		-e "s\`\$dir\`$EASYRSA_PKI\`g" \
 | 
						|
		-e "s\`\$EASYRSA_PKI\`$EASYRSA_PKI\`g" \
 | 
						|
		-e "s\`\$EASYRSA_CERT_EXPIRE\`$EASYRSA_CERT_EXPIRE\`g" \
 | 
						|
		-e "s\`\$EASYRSA_CRL_DAYS\`$EASYRSA_CRL_DAYS\`g" \
 | 
						|
		-e "s\`\$EASYRSA_DIGEST\`$EASYRSA_DIGEST\`g" \
 | 
						|
		-e "s\`\$EASYRSA_KEY_SIZE\`$EASYRSA_KEY_SIZE\`g" \
 | 
						|
		-e "s\`\$EASYRSA_DIGEST\`$EASYRSA_DIGEST\`g" \
 | 
						|
		-e "s\`\$EASYRSA_DN\`$EASYRSA_DN\`g" \
 | 
						|
		-e "s\`\$EASYRSA_REQ_COUNTRY\`$EASYRSA_REQ_COUNTRY\`g" \
 | 
						|
		-e "s\`\$EASYRSA_REQ_PROVINCE\`$EASYRSA_REQ_PROVINCE\`g" \
 | 
						|
		-e "s\`\$EASYRSA_REQ_CITY\`$EASYRSA_REQ_CITY\`g" \
 | 
						|
		-e "s\`\$EASYRSA_REQ_ORG\`$EASYRSA_REQ_ORG\`g" \
 | 
						|
		-e "s\`\$EASYRSA_REQ_OU\`$EASYRSA_REQ_OU\`g" \
 | 
						|
		-e "s\`\$EASYRSA_REQ_CN\`$EASYRSA_REQ_CN\`g" \
 | 
						|
		-e "s\`\$EASYRSA_REQ_EMAIL\`$EASYRSA_REQ_EMAIL\`g" \
 | 
						|
		${EASYRSA_EXTRA_EXTS:+-e "/^#%EXTRA_EXTS%/r $easyrsa_extra_exts"} \
 | 
						|
		"$EASYRSA_SSL_CONF" > "$easyrsa_openssl_conf" ||
 | 
						|
		die "Failed to update $easyrsa_openssl_conf"
 | 
						|
 | 
						|
	if [ "$openssl_command" = "makesafeconf" ]; then
 | 
						|
		cp "$easyrsa_openssl_conf" "$EASYRSA_SAFE_CONF"
 | 
						|
		err=$?
 | 
						|
	else
 | 
						|
		"$EASYRSA_OPENSSL" "$openssl_command" -config "$easyrsa_openssl_conf" "$@"
 | 
						|
		err=$?
 | 
						|
	fi
 | 
						|
 | 
						|
	rm -f "$easyrsa_openssl_conf"
 | 
						|
	rm -f "$easyrsa_extra_exts"
 | 
						|
	return $err
 | 
						|
} # => easyrsa_openssl
 | 
						|
 | 
						|
vars_source_check() {
 | 
						|
	# Check for defined EASYRSA_PKI
 | 
						|
	[ -n "$EASYRSA_PKI" ] || die "\
 | 
						|
EASYRSA_PKI env-var undefined"
 | 
						|
} # => vars_source_check()
 | 
						|
 | 
						|
# Verify supplied curve exists and generate curve file if needed
 | 
						|
verify_curve_ec() {
 | 
						|
	if ! "$EASYRSA_OPENSSL" ecparam -name "$EASYRSA_CURVE" > /dev/null; then
 | 
						|
		die "\
 | 
						|
Curve $EASYRSA_CURVE not found. Run openssl ecparam -list_curves to show a
 | 
						|
list of supported curves."
 | 
						|
	fi
 | 
						|
 | 
						|
	# Check that the ecparams dir exists
 | 
						|
	[ -d "$EASYRSA_EC_DIR" ] || mkdir "$EASYRSA_EC_DIR" || die "\
 | 
						|
Failed creating ecparams dir (permissions?) at:
 | 
						|
$EASYRSA_EC_DIR"
 | 
						|
 | 
						|
	# Check that the required ecparams file exists
 | 
						|
	out="$EASYRSA_EC_DIR/${EASYRSA_CURVE}.pem"
 | 
						|
	[ -f "$out" ] && return 0
 | 
						|
	"$EASYRSA_OPENSSL" ecparam -name "$EASYRSA_CURVE" -out "$out" || die "\
 | 
						|
Failed to generate ecparam file (permissions?) when writing to:
 | 
						|
$out"
 | 
						|
 | 
						|
	# Explicitly return success for caller
 | 
						|
	return 0
 | 
						|
}
 | 
						|
 | 
						|
# Verify if Edward Curve exists
 | 
						|
verify_curve_ed() {
 | 
						|
	if [ "ed25519" = "$EASYRSA_CURVE" ] && "$EASYRSA_OPENSSL" genpkey -algorithm ED25519 > /dev/null; then
 | 
						|
		return 0
 | 
						|
	elif [ "ed448" = "$EASYRSA_CURVE" ] && "$EASYRSA_OPENSSL" genpkey -algorithm ED448 > /dev/null; then
 | 
						|
		return 0
 | 
						|
	fi
 | 
						|
		die "Curve $EASYRSA_CURVE not found."
 | 
						|
}
 | 
						|
 | 
						|
verify_ssl_lib () {
 | 
						|
	# Verify EASYRSA_OPENSSL command gives expected output
 | 
						|
	if [ -z "$EASYRSA_SSL_OK" ]; then
 | 
						|
		val="$("$EASYRSA_OPENSSL" version)"
 | 
						|
		case "${val%% *}" in
 | 
						|
			OpenSSL|LibreSSL)
 | 
						|
				print "\
 | 
						|
Using SSL: $EASYRSA_OPENSSL $("$EASYRSA_OPENSSL" version)" ;;
 | 
						|
			*) die "\
 | 
						|
Missing or invalid OpenSSL
 | 
						|
Expected to find openssl command at: $EASYRSA_OPENSSL" ;;
 | 
						|
		esac
 | 
						|
	fi
 | 
						|
	EASYRSA_SSL_OK=1
 | 
						|
 | 
						|
	# Verify EASYRSA_SSL_CONF file exists
 | 
						|
	[ -f "$EASYRSA_SSL_CONF" ] || die "\
 | 
						|
The OpenSSL config file cannot be found.
 | 
						|
Expected location: $EASYRSA_SSL_CONF"
 | 
						|
} # => verify_ssl_lib ()
 | 
						|
 | 
						|
# Basic sanity-check of PKI init and complain if missing
 | 
						|
verify_pki_init() {
 | 
						|
	help_note="Run easyrsa without commands for usage and command help."
 | 
						|
 | 
						|
	# check that the pki dir exists
 | 
						|
	vars_source_check
 | 
						|
	[ -d "$EASYRSA_PKI" ] || die "\
 | 
						|
EASYRSA_PKI does not exist (perhaps you need to run init-pki)?
 | 
						|
Expected to find the EASYRSA_PKI at: $EASYRSA_PKI
 | 
						|
$help_note"
 | 
						|
 | 
						|
	# verify expected dirs present:
 | 
						|
	for i in private reqs; do
 | 
						|
		[ -d "$EASYRSA_PKI/$i" ] || die "\
 | 
						|
Missing expected directory: $i (perhaps you need to run init-pki?)
 | 
						|
$help_note"
 | 
						|
	done
 | 
						|
 | 
						|
	# verify ssl lib
 | 
						|
	verify_ssl_lib
 | 
						|
} # => verify_pki_init()
 | 
						|
 | 
						|
# Verify core CA files present
 | 
						|
verify_ca_init() {
 | 
						|
	help_note="Run without commands for usage and command help."
 | 
						|
 | 
						|
	# First check the PKI has been initialized
 | 
						|
	verify_pki_init
 | 
						|
 | 
						|
	# Verify expected files are present. Allow files to be regular files
 | 
						|
	# (or symlinks), but also pipes, for flexibility with ca.key
 | 
						|
	for i in serial index.txt index.txt.attr ca.crt private/ca.key; do
 | 
						|
		if [ ! -f "$EASYRSA_PKI/$i" ] && [ ! -p "$EASYRSA_PKI/$i" ]; then
 | 
						|
			[ "$1" = "test" ] && return 1
 | 
						|
			die "\
 | 
						|
Missing expected CA file: $i (perhaps you need to run build-ca?)
 | 
						|
$help_note"
 | 
						|
		fi
 | 
						|
	done
 | 
						|
 | 
						|
	# When operating in 'test' mode, return success.
 | 
						|
	# test callers don't care about CA-specific dir structure
 | 
						|
	[ "$1" = "test" ] && return 0
 | 
						|
 | 
						|
	# verify expected CA-specific dirs:
 | 
						|
	for i in issued certs_by_serial
 | 
						|
	do
 | 
						|
		[ -d "$EASYRSA_PKI/$i" ] || die "\
 | 
						|
Missing expected CA dir: $i (perhaps you need to run build-ca?)
 | 
						|
$help_note"
 | 
						|
	done
 | 
						|
 | 
						|
	# explicitly return success for callers
 | 
						|
	return 0
 | 
						|
 | 
						|
} # => verify_ca_init()
 | 
						|
 | 
						|
# init-pki backend:
 | 
						|
init_pki() {
 | 
						|
 | 
						|
	# If EASYRSA_PKI exists, confirm before we rm -rf (skiped with EASYRSA_BATCH)
 | 
						|
	if [ -e "$EASYRSA_PKI" ]; then
 | 
						|
		confirm "Confirm removal: " "yes" "
 | 
						|
WARNING!!!
 | 
						|
 | 
						|
You are about to remove the EASYRSA_PKI at: $EASYRSA_PKI
 | 
						|
and initialize a fresh PKI here."
 | 
						|
		# now remove it:
 | 
						|
		rm -rf "$EASYRSA_PKI" || die "Removal of PKI dir failed. Check/correct errors above"
 | 
						|
	fi
 | 
						|
 | 
						|
	# new dirs:
 | 
						|
	for i in private reqs; do
 | 
						|
		mkdir -p "$EASYRSA_PKI/$i" || die "Failed to create PKI file structure (permissions?)"
 | 
						|
	done
 | 
						|
	
 | 
						|
	# Create $EASYRSA_SAFE_CONF ($OPENSSL_CONF) prevents bogus warnings (especially useful on win32)
 | 
						|
	if [ ! -f "$EASYRSA_SSL_CONF" ] && [ -f "$EASYRSA/openssl-easyrsa.cnf" ];
 | 
						|
	then
 | 
						|
		cp "$EASYRSA/openssl-easyrsa.cnf" "$EASYRSA_SSL_CONF"
 | 
						|
		easyrsa_openssl makesafeconf
 | 
						|
	fi
 | 
						|
 | 
						|
	notice "\
 | 
						|
init-pki complete; you may now create a CA or requests.
 | 
						|
Your newly created PKI dir is: $EASYRSA_PKI
 | 
						|
"
 | 
						|
	return 0
 | 
						|
} # => init_pki()
 | 
						|
 | 
						|
hide_read_pass()
 | 
						|
{
 | 
						|
	# shellcheck disable=SC2039
 | 
						|
	if stty -echo 2>/dev/null; then
 | 
						|
		read -r "$@"
 | 
						|
		stty echo
 | 
						|
	elif (set +o echo 2>/dev/null); then
 | 
						|
		set +o echo
 | 
						|
		read -r "$@"
 | 
						|
		set -o echo
 | 
						|
	elif (echo | read -r -s 2>/dev/null) ; then
 | 
						|
		read -r -s "$@"
 | 
						|
	else
 | 
						|
		warn "Could not disable echo. Password will be shown on screen!"
 | 
						|
		read -r "$@"
 | 
						|
	fi
 | 
						|
} # => hide_read_pass()
 | 
						|
 | 
						|
# build-ca backend:
 | 
						|
build_ca() {
 | 
						|
	opts=""
 | 
						|
	sub_ca=""
 | 
						|
	nopass=""
 | 
						|
	crypto="-aes256"
 | 
						|
	while [ -n "$1" ]; do
 | 
						|
		case "$1" in
 | 
						|
			intca) sub_ca=1 ;;
 | 
						|
			subca) sub_ca=1 ;;
 | 
						|
			nopass) nopass=1 ;;
 | 
						|
			*) warn "Ignoring unknown command option: '$1'" ;;
 | 
						|
		esac
 | 
						|
		shift
 | 
						|
	done
 | 
						|
 | 
						|
	verify_pki_init
 | 
						|
	[ "$EASYRSA_ALGO" = "ec" ] && verify_curve_ec
 | 
						|
	[ "$EASYRSA_ALGO" = "ed" ] && verify_curve_ed
 | 
						|
 | 
						|
	# setup for the simpler intermediate CA situation and overwrite with root-CA if needed:
 | 
						|
	out_file="$EASYRSA_PKI/reqs/ca.req"
 | 
						|
	out_key="$EASYRSA_PKI/private/ca.key"
 | 
						|
	if [ ! $sub_ca ]; then
 | 
						|
		out_file="$EASYRSA_PKI/ca.crt"
 | 
						|
		opts="$opts -x509 -days $EASYRSA_CA_EXPIRE "
 | 
						|
	fi
 | 
						|
 | 
						|
	# Test for existing CA, and complain if already present
 | 
						|
	if verify_ca_init test; then
 | 
						|
		die "\
 | 
						|
Unable to create a CA as you already seem to have one set up.
 | 
						|
If you intended to start a new CA, run init-pki first."
 | 
						|
	fi
 | 
						|
	# If a private key exists here, a intermediate ca was created but not signed.
 | 
						|
	# Notify the user and require a signed ca.crt or a init-pki:
 | 
						|
	[ -f "$out_key" ] && \
 | 
						|
		die "\
 | 
						|
A CA private key exists but no ca.crt is found in your PKI dir of:
 | 
						|
$EASYRSA_PKI
 | 
						|
Refusing to create a new CA keypair as this operation would overwrite your
 | 
						|
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;
 | 
						|
	do
 | 
						|
		mkdir -p "$EASYRSA_PKI/$i" || die "$err_file"
 | 
						|
	done
 | 
						|
	printf "" > "$EASYRSA_PKI/index.txt" || die "$err_file"
 | 
						|
	printf "" > "$EASYRSA_PKI/index.txt.attr" || die "$err_file"
 | 
						|
	print "01" > "$EASYRSA_PKI/serial" || die "$err_file"
 | 
						|
 | 
						|
	# Default CN only when not in global EASYRSA_BATCH mode:
 | 
						|
	# shellcheck disable=SC2015
 | 
						|
	[ "$EASYRSA_BATCH" ] && opts="$opts -batch" || export EASYRSA_REQ_CN="Easy-RSA CA"
 | 
						|
 | 
						|
	out_key_tmp="$(easyrsa_mktemp)" || die "Failed to create temporary file"
 | 
						|
	out_file_tmp="$(easyrsa_mktemp)" || die "Failed to create temporary file"
 | 
						|
	# Get password from user if necessary
 | 
						|
	if [ ! $nopass ] && ( [ -z "$EASYRSA_PASSOUT" ] || [ -z "$EASYRSA_PASSIN" ] ); then
 | 
						|
		out_key_pass_tmp="$(easyrsa_mktemp)" || die "Failed to create temporary file"
 | 
						|
		echo
 | 
						|
		printf "Enter New CA Key Passphrase: "
 | 
						|
		hide_read_pass kpass
 | 
						|
		echo
 | 
						|
		printf "Re-Enter New CA Key Passphrase: "
 | 
						|
		hide_read_pass kpass2
 | 
						|
		echo
 | 
						|
		# shellcheck disable=2154
 | 
						|
		if [ "$kpass" = "$kpass2" ];
 | 
						|
		then
 | 
						|
			printf "%s" "$kpass" > "$out_key_pass_tmp"
 | 
						|
		else
 | 
						|
			die "Passphrases do not match."
 | 
						|
		fi
 | 
						|
	fi
 | 
						|
 | 
						|
	# create the CA key using AES256
 | 
						|
	crypto_opts=""
 | 
						|
	if [ ! $nopass ]; then
 | 
						|
		crypto_opts="$crypto"
 | 
						|
		if [ -z "$EASYRSA_PASSOUT" ]; then
 | 
						|
		    if [ "ed" = "$EASYRSA_ALGO" ]; then
 | 
						|
                crypto_opts="$crypto_opts -pass file:$out_key_pass_tmp"
 | 
						|
            else
 | 
						|
                crypto_opts="$crypto_opts -passout file:$out_key_pass_tmp"
 | 
						|
            fi
 | 
						|
        fi
 | 
						|
	fi
 | 
						|
	if [ "$EASYRSA_ALGO" = "rsa" ]; then
 | 
						|
		#shellcheck disable=SC2086
 | 
						|
		"$EASYRSA_OPENSSL" genrsa -out "$out_key_tmp" $crypto_opts ${EASYRSA_PASSOUT:+-passout "$EASYRSA_PASSOUT"} "$EASYRSA_ALGO_PARAMS" || \
 | 
						|
			die "Failed create CA private key"
 | 
						|
	elif [ "$EASYRSA_ALGO" = "ec" ]; then
 | 
						|
		#shellcheck disable=SC2086
 | 
						|
		"$EASYRSA_OPENSSL" ecparam -in "$EASYRSA_ALGO_PARAMS" -genkey | \
 | 
						|
			"$EASYRSA_OPENSSL" ec -out "$out_key_tmp" $crypto_opts ${EASYRSA_PASSOUT:+-passout "$EASYRSA_PASSOUT"} || \
 | 
						|
			die "Failed create CA private key"
 | 
						|
	elif [ "ed" = "$EASYRSA_ALGO" ]; then
 | 
						|
		if [ "ed25519" = "$EASYRSA_CURVE" ]; then
 | 
						|
			"$EASYRSA_OPENSSL" genpkey -algorithm ED25519 -out $out_key_tmp $crypto_opts ${EASYRSA_PASSOUT:+-pass "$EASYRSA_PASSOUT"} || \
 | 
						|
			die "Failed create CA private key"
 | 
						|
		elif [ "ed448" = "$EASYRSA_CURVE" ]; then
 | 
						|
			"$EASYRSA_OPENSSL" genpkey -algorithm ED448 -out $out_key_tmp $crypto_opts ${EASYRSA_PASSOUT:+-pass "$EASYRSA_PASSOUT"} || \
 | 
						|
			die "Failed create CA private key"
 | 
						|
		fi
 | 
						|
	fi
 | 
						|
 | 
						|
	# create the CA keypair:
 | 
						|
	crypto_opts=""
 | 
						|
	[ ! $nopass ] && [ -z "$EASYRSA_PASSIN" ] && crypto_opts="-passin file:$out_key_pass_tmp"
 | 
						|
 | 
						|
	#shellcheck disable=SC2086
 | 
						|
	easyrsa_openssl req -utf8 -new -key "$out_key_tmp" \
 | 
						|
		-keyout "$out_key_tmp" -out "$out_file_tmp" $crypto_opts $opts ${EASYRSA_PASSIN:+-passin "$EASYRSA_PASSIN"} || \
 | 
						|
		die "Failed to build the CA"
 | 
						|
 | 
						|
	mv "$out_key_tmp" "$out_key"
 | 
						|
	mv "$out_file_tmp" "$out_file"
 | 
						|
	[ -f "$out_key_pass_tmp" ] && rm "$out_key_pass_tmp"
 | 
						|
 | 
						|
	# Success messages
 | 
						|
	if [ $sub_ca ]; then
 | 
						|
		notice "\
 | 
						|
NOTE: Your intermediate CA request is at $out_file
 | 
						|
and now must be sent to your parent CA for signing. Place your resulting cert
 | 
						|
at $EASYRSA_PKI/ca.crt prior to signing operations.
 | 
						|
"
 | 
						|
	else	notice "\
 | 
						|
CA creation complete and you may now import and sign cert requests.
 | 
						|
Your new CA certificate file for publishing is at:
 | 
						|
$out_file
 | 
						|
"
 | 
						|
	fi
 | 
						|
	return 0
 | 
						|
} # => build_ca()
 | 
						|
 | 
						|
# gen-dh backend:
 | 
						|
gen_dh() {
 | 
						|
	verify_pki_init
 | 
						|
 | 
						|
	out_file="$EASYRSA_PKI/dh.pem"
 | 
						|
 | 
						|
	# check to see if we already have a dh parameters file
 | 
						|
	if [ -e "$EASYRSA_PKI/dh.pem" ]; then
 | 
						|
		if [ "$EASYRSA_BATCH" = "1" ]; then
 | 
						|
			# if batch is enabled, die
 | 
						|
			die "file $EASYRSA_PKI/dh.pem already exists!"
 | 
						|
		else
 | 
						|
			# warn the user, give them a chance to force overwrite
 | 
						|
			confirm "Overwrite?  " "yes" "*** File $EASYRSA_PKI/dh.pem already exists! ***"
 | 
						|
		fi
 | 
						|
	fi
 | 
						|
 | 
						|
	"$EASYRSA_OPENSSL" dhparam -out "$out_file" "$EASYRSA_KEY_SIZE" || \
 | 
						|
		die "Failed to build DH params"
 | 
						|
	notice "\
 | 
						|
DH parameters of size $EASYRSA_KEY_SIZE created at $out_file
 | 
						|
"
 | 
						|
	return 0
 | 
						|
} # => gen_dh()
 | 
						|
 | 
						|
# gen-req backend:
 | 
						|
gen_req() {
 | 
						|
	# pull filename base and use as default interactive CommonName:
 | 
						|
	[ -n "$1" ] || die "\
 | 
						|
Error: gen-req must have a file base as the first argument.
 | 
						|
Run easyrsa without commands for usage and commands."
 | 
						|
	key_out="$EASYRSA_PKI/private/$1.key"
 | 
						|
	req_out="$EASYRSA_PKI/reqs/$1.req"
 | 
						|
	[ ! "$EASYRSA_BATCH" ] && EASYRSA_REQ_CN="$1"
 | 
						|
	shift
 | 
						|
 | 
						|
	# function opts support
 | 
						|
	opts=
 | 
						|
	while [ -n "$1" ]; do
 | 
						|
		case "$1" in
 | 
						|
			nopass) opts="$opts -nodes" ;;
 | 
						|
			# batch flag supports internal callers needing silent operation
 | 
						|
			batch) EASYRSA_BATCH=1 ;;
 | 
						|
			*) warn "Ignoring unknown command option: '$1'" ;;
 | 
						|
		esac
 | 
						|
		shift
 | 
						|
	done
 | 
						|
 | 
						|
	verify_pki_init
 | 
						|
	[ "$EASYRSA_ALGO" = "ec" ] && verify_curve_ec
 | 
						|
	[ "$EASYRSA_ALGO" = "ed" ] && verify_curve_ed
 | 
						|
 | 
						|
	# don't wipe out an existing private key without confirmation
 | 
						|
	[ -f "$key_out" ] && confirm "Confirm key overwrite: " "yes" "\
 | 
						|
 | 
						|
WARNING!!!
 | 
						|
 | 
						|
An existing private key was found at $key_out
 | 
						|
Continuing with key generation will replace this key."
 | 
						|
 | 
						|
	# When EASYRSA_EXTRA_EXTS is defined, append it to openssl's [req] section:
 | 
						|
	if [ -n "$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
 | 
						|
		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
 | 
						|
 | 
						|
	key_out_tmp="$(easyrsa_mktemp)" || die "Failed to create temporary file"
 | 
						|
	req_out_tmp="$(easyrsa_mktemp)" || die "Failed to create temporary file"
 | 
						|
	# generate request
 | 
						|
	[ $EASYRSA_BATCH ] && opts="$opts -batch"
 | 
						|
	# shellcheck disable=2086,2148
 | 
						|
	algo_opts=""
 | 
						|
	if [ "ed" = "$EASYRSA_ALGO" ]; then
 | 
						|
		algo_opts=" -newkey $EASYRSA_CURVE "
 | 
						|
	else
 | 
						|
		algo_opts=" -newkey $EASYRSA_ALGO:$EASYRSA_ALGO_PARAMS "
 | 
						|
	fi
 | 
						|
	easyrsa_openssl req -utf8 -new $algo_opts \
 | 
						|
		-keyout "$key_out_tmp" -out "$req_out_tmp" $opts ${EASYRSA_PASSOUT:+-passout "$EASYRSA_PASSOUT"} \
 | 
						|
		|| die "Failed to generate request"
 | 
						|
	mv "$key_out_tmp" "$key_out"
 | 
						|
	mv "$req_out_tmp" "$req_out"
 | 
						|
	notice "\
 | 
						|
Keypair and certificate request completed. Your files are:
 | 
						|
req: $req_out
 | 
						|
key: $key_out
 | 
						|
"
 | 
						|
	return 0
 | 
						|
} # => gen_req()
 | 
						|
 | 
						|
# common signing backend
 | 
						|
sign_req() {
 | 
						|
	crt_type="$1"
 | 
						|
	opts=""
 | 
						|
	req_in="$EASYRSA_PKI/reqs/$2.req"
 | 
						|
	crt_out="$EASYRSA_PKI/issued/$2.crt"
 | 
						|
 | 
						|
	# Randomize Serial number
 | 
						|
	if [ "$EASYRSA_RAND_SN" != "no" ];
 | 
						|
	then
 | 
						|
		i=""
 | 
						|
		serial=""
 | 
						|
		check_serial=""
 | 
						|
		for i in 1 2 3 4 5; do
 | 
						|
			"$EASYRSA_OPENSSL" rand -hex -out "$EASYRSA_PKI/serial" 16
 | 
						|
			serial="$(cat "$EASYRSA_PKI/serial")"
 | 
						|
			check_serial="$("$EASYRSA_OPENSSL" ca -config "$EASYRSA_SSL_CONF" -status "$serial" 2>&1)"
 | 
						|
			case "$check_serial" in
 | 
						|
				*"not present in db"*) break ;;
 | 
						|
				*) continue ;;
 | 
						|
			esac
 | 
						|
		done
 | 
						|
	fi
 | 
						|
 | 
						|
	# Support batch by internal caller:
 | 
						|
	[ "$3" = "batch" ] && EASYRSA_BATCH=1
 | 
						|
 | 
						|
	verify_ca_init
 | 
						|
 | 
						|
	# Check argument sanity:
 | 
						|
	[ -n "$2" ] || die "\
 | 
						|
Incorrect number of arguments provided to sign-req:
 | 
						|
expected 2, got $# (see command help for usage)"
 | 
						|
 | 
						|
	# Cert type must exist under the EASYRSA_EXT_DIR
 | 
						|
	[ -r "$EASYRSA_EXT_DIR/$crt_type" ] || die "\
 | 
						|
Unknown cert type '$crt_type'"
 | 
						|
 | 
						|
	# Request file must exist
 | 
						|
	[ -f "$req_in" ] || die "\
 | 
						|
No request found for the input: '$2'
 | 
						|
Expected to find the request at: $req_in"
 | 
						|
 | 
						|
	# Confirm input is a cert req
 | 
						|
	verify_file req "$req_in" || die "\
 | 
						|
The certificate request file is not in a valid X509 request format.
 | 
						|
File Path: $req_in"
 | 
						|
 | 
						|
	# Display the request subject in an easy-to-read format
 | 
						|
	# Confirm the user wishes to sign this request
 | 
						|
	confirm "Confirm request details: " "yes" "
 | 
						|
You are about to sign the following certificate.
 | 
						|
Please check over the details shown below for accuracy. Note that this request
 | 
						|
has not been cryptographically verified. Please be sure it came from a trusted
 | 
						|
source or that you have verified the request checksum with the sender.
 | 
						|
 | 
						|
Request subject, to be signed as a $crt_type certificate for $EASYRSA_CERT_EXPIRE days:
 | 
						|
 | 
						|
$(display_dn req "$req_in")
 | 
						|
"	# => confirm end
 | 
						|
 | 
						|
	# Generate the extensions file for this cert:
 | 
						|
	ext_tmp="$(easyrsa_mktemp)" || die "Failed to create temporary file"
 | 
						|
	{
 | 
						|
		# Append first any COMMON file (if present) then the cert-type extensions
 | 
						|
		cat "$EASYRSA_EXT_DIR/COMMON"
 | 
						|
		cat "$EASYRSA_EXT_DIR/$crt_type"
 | 
						|
		# copy req extensions
 | 
						|
		[ "$EASYRSA_CP_EXT" ] && print "copy_extensions = copy"
 | 
						|
 | 
						|
		# Support a dynamic CA path length when present:
 | 
						|
		[ "$crt_type" = "ca" ] && [ -n "$EASYRSA_SUBCA_LEN" ] && \
 | 
						|
			print "basicConstraints = CA:TRUE, pathlen:$EASYRSA_SUBCA_LEN"
 | 
						|
 | 
						|
		# Deprecated Netscape extension support, if enabled
 | 
						|
		if print "$EASYRSA_NS_SUPPORT" | awk_yesno; then
 | 
						|
			[ -n "$EASYRSA_NS_COMMENT" ] && \
 | 
						|
				print "nsComment = \"$EASYRSA_NS_COMMENT\""
 | 
						|
			case "$crt_type" in
 | 
						|
				serverClient)	print "nsCertType = serverClient" ;;
 | 
						|
				server)		print "nsCertType = server" ;;
 | 
						|
				client)		print "nsCertType = client" ;;
 | 
						|
				ca)		print "nsCertType = sslCA" ;;
 | 
						|
			esac
 | 
						|
		fi
 | 
						|
 | 
						|
		# If type is server and no subjectAltName was requested,
 | 
						|
		# add one to the extensions file
 | 
						|
		if [ "$crt_type" = 'server' ] || [ "$crt_type" = 'serverClient' ];
 | 
						|
		then
 | 
						|
			echo "$EASYRSA_EXTRA_EXTS" | grep -q subjectAltName
 | 
						|
			if [ $? -ne 0 ];
 | 
						|
			then
 | 
						|
				san=$(display_san req "$req_in")
 | 
						|
 | 
						|
				if [ -n "$san" ];
 | 
						|
				then
 | 
						|
					print "subjectAltName = $san"
 | 
						|
				else
 | 
						|
					default_server_san "$req_in"
 | 
						|
				fi
 | 
						|
			fi
 | 
						|
		fi
 | 
						|
 | 
						|
		# Add any advanced extensions supplied by env-var:
 | 
						|
		[ -n "$EASYRSA_EXTRA_EXTS" ] && print "$EASYRSA_EXTRA_EXTS"
 | 
						|
 | 
						|
		: # needed to keep die from inherting the above test
 | 
						|
	} > "$ext_tmp" || die "\
 | 
						|
Failed to create temp extension file (bad permissions?) at:
 | 
						|
$ext_tmp"
 | 
						|
 | 
						|
	# sign request
 | 
						|
	crt_out_tmp="$(easyrsa_mktemp)" || die "Failed to create temporary file"
 | 
						|
	easyrsa_openssl ca -utf8 -in "$req_in" -out "$crt_out_tmp" \
 | 
						|
		-extfile "$ext_tmp" -days "$EASYRSA_CERT_EXPIRE" -batch $opts ${EASYRSA_PASSIN:+-passin "$EASYRSA_PASSIN"} \
 | 
						|
		|| die "signing failed (openssl output above may have more detail)"
 | 
						|
	mv "$crt_out_tmp" "$crt_out"
 | 
						|
	rm -f "$ext_tmp"
 | 
						|
	notice "\
 | 
						|
Certificate created at: $crt_out
 | 
						|
"
 | 
						|
	return 0
 | 
						|
} # => sign_req()
 | 
						|
 | 
						|
# common build backend
 | 
						|
# used to generate+sign in 1 step
 | 
						|
build_full() {
 | 
						|
	verify_ca_init
 | 
						|
 | 
						|
	# pull filename base:
 | 
						|
	[ -n "$2" ] || die "\
 | 
						|
Error: didn't find a file base name as the first argument.
 | 
						|
Run easyrsa without commands for usage and commands."
 | 
						|
	crt_type="$1" name="$2"
 | 
						|
	req_out="$EASYRSA_PKI/reqs/$2.req"
 | 
						|
	key_out="$EASYRSA_PKI/private/$2.key"
 | 
						|
	crt_out="$EASYRSA_PKI/issued/$2.crt"
 | 
						|
	shift 2
 | 
						|
 | 
						|
	# function opts support
 | 
						|
	req_opts=
 | 
						|
	while [ -n "$1" ]; do
 | 
						|
		case "$1" in
 | 
						|
			nopass) req_opts="$req_opts nopass" ;;
 | 
						|
			inline) EASYRSA_INLINE=1 ;;
 | 
						|
			*) warn "Ignoring unknown command option: '$1'" ;;
 | 
						|
		esac
 | 
						|
		shift
 | 
						|
	done
 | 
						|
 | 
						|
	# abort on existing req/key/crt files
 | 
						|
	err_exists="\
 | 
						|
file already exists. Aborting build to avoid overwriting this file.
 | 
						|
If you wish to continue, please use a different name or remove the file.
 | 
						|
Matching file found at: "
 | 
						|
	[ -f "$req_out" ] && die "Request $err_exists $req_out"
 | 
						|
	[ -f "$key_out" ] && die "Key $err_exists $key_out"
 | 
						|
	[ -f "$crt_out" ] && die "Certificate $err_exists $crt_out"
 | 
						|
 | 
						|
	# create request
 | 
						|
	EASYRSA_REQ_CN="$name"
 | 
						|
	#shellcheck disable=SC2086
 | 
						|
	gen_req "$name" batch $req_opts
 | 
						|
 | 
						|
	# Sign it
 | 
						|
	( sign_req "$crt_type" "$name" batch ) || {
 | 
						|
		rm -f "$req_out" "$key_out"
 | 
						|
		die "Failed to sign '$name'"
 | 
						|
	}
 | 
						|
 | 
						|
	# inline it
 | 
						|
	if [ $EASYRSA_INLINE ]; then
 | 
						|
		inline_creds
 | 
						|
	fi
 | 
						|
} # => build_full()
 | 
						|
 | 
						|
# Create inline credentials file for this node
 | 
						|
inline_creds ()
 | 
						|
{
 | 
						|
	[ -f "$EASYRSA_PKI/$EASYRSA_REQ_CN.creds" ] \
 | 
						|
	&& die "Inline file exists: $EASYRSA_PKI/$EASYRSA_REQ_CN.creds"
 | 
						|
	{
 | 
						|
		printf "%s\n" "# $crt_type: $EASYRSA_REQ_CN"
 | 
						|
		printf "%s\n" ""
 | 
						|
		printf "%s\n" "<ca>"
 | 
						|
		cat "$EASYRSA_PKI/ca.crt"
 | 
						|
		printf "%s\n" "</ca>"
 | 
						|
		printf "%s\n" ""
 | 
						|
		printf "%s\n" "<cert>"
 | 
						|
		cat "$crt_out"
 | 
						|
		printf "%s\n" "</cert>"
 | 
						|
		printf "%s\n" ""
 | 
						|
		printf "%s\n" "<key>"
 | 
						|
		cat "$key_out"
 | 
						|
		printf "%s\n" "</key>"
 | 
						|
		printf "%s\n" ""
 | 
						|
	} > "$EASYRSA_PKI/$EASYRSA_REQ_CN.creds"
 | 
						|
} # => inline_creds ()
 | 
						|
 | 
						|
# revoke backend
 | 
						|
revoke() {
 | 
						|
	verify_ca_init
 | 
						|
 | 
						|
	# pull filename base:
 | 
						|
	[ -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"
 | 
						|
 | 
						|
	opts=""
 | 
						|
	if [ "$2" ]; then
 | 
						|
		opts="$opts -crl_reason $2"
 | 
						|
	fi
 | 
						|
	
 | 
						|
	verify_file x509 "$crt_in" || die "\
 | 
						|
Unable to revoke as the input file is not a valid certificate. Unexpected
 | 
						|
input in file: $crt_in"
 | 
						|
 | 
						|
	# confirm operation by displaying DN:
 | 
						|
	confirm "Continue with revocation: " "yes" "
 | 
						|
Please confirm you wish to revoke the certificate with the following subject:
 | 
						|
 | 
						|
$(display_dn x509 "$crt_in")
 | 
						|
"	# => confirm end
 | 
						|
 | 
						|
	# referenced cert must exist:
 | 
						|
	[ -f "$crt_in" ] || die "\
 | 
						|
Unable to revoke as no certificate was found. Certificate was expected
 | 
						|
at: $crt_in"
 | 
						|
 | 
						|
	# shellcheck disable=SC2086
 | 
						|
	easyrsa_openssl ca -utf8 -revoke "$crt_in" ${EASYRSA_PASSIN:+-passin "$EASYRSA_PASSIN"} $opts || die "\
 | 
						|
Failed to revoke certificate: revocation command failed."
 | 
						|
 | 
						|
	# move revoked files so we can reissue certificates with the same name
 | 
						|
	move_revoked "$1"
 | 
						|
 | 
						|
	notice "\
 | 
						|
IMPORTANT!!!
 | 
						|
 | 
						|
Revocation was successful. You must run gen-crl and upload a CRL to your
 | 
						|
infrastructure in order to prevent the revoked cert from being accepted.
 | 
						|
"	# => notice end
 | 
						|
	return 0
 | 
						|
} #= revoke()
 | 
						|
 | 
						|
# move-revoked
 | 
						|
# moves revoked certificates to an alternative folder
 | 
						|
# allows reissuing certificates with the same name
 | 
						|
move_revoked() {
 | 
						|
	verify_ca_init
 | 
						|
 | 
						|
	[ -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"
 | 
						|
 | 
						|
	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"
 | 
						|
 | 
						|
	# 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"
 | 
						|
 | 
						|
	# 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"
 | 
						|
 | 
						|
	# only move the key if we have it
 | 
						|
	[ -e "$key_in" ] && mv "$key_in" "$key_by_serial_revoked"
 | 
						|
 | 
						|
	# move the rest of the files (p12, p7, ...)
 | 
						|
	# shellcheck disable=SC2231
 | 
						|
	for file in $EASYRSA_PKI/private/$1\.???
 | 
						|
	do
 | 
						|
		# get file extension
 | 
						|
		file_ext="${file##*.}"
 | 
						|
 | 
						|
		[ -f "$file" ] && mv "$file" "$EASYRSA_PKI/revoked/private_by_serial/$cert_serial.$file_ext"
 | 
						|
	done
 | 
						|
 | 
						|
	# remove the dublicate certificate in the certs_by_serial folder
 | 
						|
	rm "$crt_by_serial"
 | 
						|
 | 
						|
	return 0
 | 
						|
 | 
						|
} #= move_revoked()
 | 
						|
 | 
						|
# renew backend
 | 
						|
renew() {
 | 
						|
	verify_ca_init
 | 
						|
 | 
						|
	# pull filename base:
 | 
						|
	[ -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"
 | 
						|
 | 
						|
	opts=""
 | 
						|
	if [ "$2" ]; then
 | 
						|
		opts="$2"
 | 
						|
	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"
 | 
						|
 | 
						|
	# confirm operation by displaying DN:
 | 
						|
	confirm "Continue with renew: " "yes" "
 | 
						|
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"
 | 
						|
 | 
						|
	# Check if old cert is expired or expires within 30 days
 | 
						|
	expire_date=$(
 | 
						|
		easyrsa_openssl x509 -in "$crt_in" -noout -enddate |
 | 
						|
		sed 's/^notAfter=//'
 | 
						|
		)
 | 
						|
        case $(uname 2>/dev/null) in
 | 
						|
        	"Darwin"|*"BSD")
 | 
						|
                	expire_date=$(date -j -f '%b %d %T %Y %Z' "$expire_date" +%s)
 | 
						|
                	allow_renew_date=$(date -j -v"+${EASYRSA_CERT_RENEW}d" +%s)
 | 
						|
                	;;
 | 
						|
          	*)
 | 
						|
                	# This works on Windows, too, since uname doesn't exist and this is catch-all
 | 
						|
                	expire_date=$(date -d "$expire_date" +%s)
 | 
						|
                	allow_renew_date=$(date -d "+${EASYRSA_CERT_RENEW}day" +%s)
 | 
						|
                	;;
 | 
						|
        esac
 | 
						|
 | 
						|
	[ "$expire_date" -lt "$allow_renew_date" ] || die "\
 | 
						|
Certificate expires in more than $EASYRSA_CERT_RENEW days.
 | 
						|
Renewal not allowed."
 | 
						|
 | 
						|
	# Extract certificate usage from old cert
 | 
						|
	cert_ext_key_usage=$(
 | 
						|
		easyrsa_openssl x509 -in "$crt_in" -noout -text |
 | 
						|
		sed -n "/X509v3 Extended Key Usage:/{n;s/^ *//g;p;}"
 | 
						|
		)
 | 
						|
	case $cert_ext_key_usage in
 | 
						|
		"TLS Web Client Authentication")
 | 
						|
			cert_type=client
 | 
						|
			;;
 | 
						|
		"TLS Web Server Authentication")
 | 
						|
			cert_type=server
 | 
						|
			;;
 | 
						|
		"TLS Web Server Authentication, TLS Web Client Authentication")
 | 
						|
			cert_type=serverClient
 | 
						|
			;;
 | 
						|
	esac
 | 
						|
 | 
						|
	# Use SAN from --subject-alt-name if set else use SAN from old cert
 | 
						|
	echo "$EASYRSA_EXTRA_EXTS" | grep -q subjectAltName || \
 | 
						|
	{
 | 
						|
		san=$(
 | 
						|
			easyrsa_openssl x509 -in "$crt_in" -noout -text |
 | 
						|
			sed -n "/X509v3 Subject Alternative Name:/{n;s/IP Address:/IP:/;s/ //g;p;}"
 | 
						|
			)
 | 
						|
		[ -n "$san" ] && export EASYRSA_EXTRA_EXTS="\
 | 
						|
$EASYRSA_EXTRA_EXTS
 | 
						|
subjectAltName = $san"
 | 
						|
	}
 | 
						|
 | 
						|
	# 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"
 | 
						|
 | 
						|
	# renew certificate
 | 
						|
	# shellcheck disable=SC2086
 | 
						|
	build_full $cert_type $1 $opts || die "\
 | 
						|
Failed to renew certificate: renew command failed."
 | 
						|
 | 
						|
	notice "\
 | 
						|
IMPORTANT!!!
 | 
						|
 | 
						|
Renew was successful.
 | 
						|
You may want to revoke the old certificate once the new one has been deployed.
 | 
						|
"	# => notice end
 | 
						|
	return 0
 | 
						|
} #= renew()
 | 
						|
 | 
						|
# move-renewed
 | 
						|
# moves renewed certificates to an alternative folder
 | 
						|
# allows reissuing certificates with the same name
 | 
						|
move_renewed() {
 | 
						|
	verify_ca_init
 | 
						|
 | 
						|
	[ -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"
 | 
						|
 | 
						|
	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"
 | 
						|
 | 
						|
	# 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"
 | 
						|
 | 
						|
	# 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"
 | 
						|
 | 
						|
	# only move the key if we have it
 | 
						|
	[ -e "$key_in" ] && mv "$key_in" "$key_by_serial_renewed"
 | 
						|
 | 
						|
	# move the rest of the files (p12, p7, ...)
 | 
						|
	# shellcheck disable=SC2231
 | 
						|
	for file in $EASYRSA_PKI/private/$1\.???
 | 
						|
	do
 | 
						|
		# get file extension
 | 
						|
		file_ext="${file##*.}"
 | 
						|
 | 
						|
		[ -f "$file" ] && mv "$file" "$EASYRSA_PKI/renewed/private_by_serial/$cert_serial.$file_ext"
 | 
						|
	done
 | 
						|
 | 
						|
	# remove the duplicate certificate in the certs_by_serial folder
 | 
						|
	rm "$crt_by_serial"
 | 
						|
 | 
						|
	return 0
 | 
						|
 | 
						|
} #= move_renewed()
 | 
						|
 | 
						|
# gen-crl backend
 | 
						|
gen_crl() {
 | 
						|
	verify_ca_init
 | 
						|
 | 
						|
	out_file="$EASYRSA_PKI/crl.pem"
 | 
						|
	out_file_tmp="$(easyrsa_mktemp)" || die "Failed to create temporary file"
 | 
						|
	easyrsa_openssl ca -utf8 -gencrl -out "$out_file_tmp" ${EASYRSA_PASSIN:+-passin "$EASYRSA_PASSIN"} || die "\
 | 
						|
CRL Generation failed.
 | 
						|
"
 | 
						|
	mv "$out_file_tmp" "$out_file"
 | 
						|
 | 
						|
	notice "\
 | 
						|
An updated CRL has been created.
 | 
						|
CRL file: $out_file
 | 
						|
"
 | 
						|
	return 0
 | 
						|
} # => gen_crl()
 | 
						|
 | 
						|
# import-req backend
 | 
						|
import_req() {
 | 
						|
	verify_pki_init
 | 
						|
 | 
						|
	# pull passed paths
 | 
						|
	in_req="$1" short_name="$2"
 | 
						|
	out_req="$EASYRSA_PKI/reqs/$2.req" 
 | 
						|
 | 
						|
	[ -n "$short_name" ] || die "\
 | 
						|
Unable to import: incorrect command syntax.
 | 
						|
Run easyrsa without commands for usage and command help."
 | 
						|
 | 
						|
	verify_file req "$in_req" || die "\
 | 
						|
The input file does not appear to be a certificate request. Aborting import.
 | 
						|
File Path: $in_req"
 | 
						|
 | 
						|
	# destination must not exist
 | 
						|
	[ -f "$out_req" ] && die "\
 | 
						|
Unable to import the request as the destination file already exists.
 | 
						|
Please choose a different name for your imported request file.
 | 
						|
Existing file at: $out_req"
 | 
						|
	
 | 
						|
	# now import it
 | 
						|
	cp "$in_req" "$out_req"
 | 
						|
 | 
						|
	notice "\
 | 
						|
The request has been successfully imported with a short name of: $short_name
 | 
						|
You may now use this name to perform signing operations on this request.
 | 
						|
"
 | 
						|
	return 0
 | 
						|
} # => import_req()
 | 
						|
 | 
						|
# export pkcs#12 or pkcs#7
 | 
						|
export_pkcs() {
 | 
						|
	pkcs_type="$1"
 | 
						|
	shift
 | 
						|
 | 
						|
	[ -n "$1" ] || die "\
 | 
						|
Unable to export p12: incorrect command syntax.
 | 
						|
Run easyrsa without commands for usage and command help."
 | 
						|
 | 
						|
	short_name="$1"
 | 
						|
	crt_in="$EASYRSA_PKI/issued/$1.crt"
 | 
						|
	key_in="$EASYRSA_PKI/private/$1.key"
 | 
						|
	crt_ca="$EASYRSA_PKI/ca.crt"
 | 
						|
	shift
 | 
						|
 | 
						|
	verify_pki_init
 | 
						|
 | 
						|
	# opts support
 | 
						|
	want_ca=1
 | 
						|
	want_key=1
 | 
						|
	want_pass=1
 | 
						|
	while [ -n "$1" ]; do
 | 
						|
		case "$1" in
 | 
						|
			noca) want_ca="" ;;
 | 
						|
			nokey) want_key="" ;;
 | 
						|
			nopass) want_pass="" ;;
 | 
						|
			*) warn "Ignoring unknown command option: '$1'" ;;
 | 
						|
		esac
 | 
						|
		shift
 | 
						|
	done
 | 
						|
 | 
						|
	pkcs_opts=
 | 
						|
	if [ $want_ca ]; then
 | 
						|
		verify_file x509 "$crt_ca" || die "\
 | 
						|
Unable to include CA cert in the $pkcs_type output (missing file, or use noca option.)
 | 
						|
Missing file expected at: $crt_ca"
 | 
						|
		pkcs_opts="$pkcs_opts -certfile $crt_ca"
 | 
						|
	fi
 | 
						|
 | 
						|
	# input files must exist
 | 
						|
	verify_file x509 "$crt_in" || die "\
 | 
						|
Unable to export $pkcs_type for short name '$short_name' without the certificate.
 | 
						|
Missing cert expected at: $crt_in"
 | 
						|
 | 
						|
	case "$pkcs_type" in
 | 
						|
	p12)
 | 
						|
		pkcs_out="$EASYRSA_PKI/private/$short_name.p12"
 | 
						|
 | 
						|
		if [ $want_key ]; then
 | 
						|
			[ -f "$key_in" ] || die "\
 | 
						|
Unable to export p12 for short name '$short_name' without the key
 | 
						|
(if you want a p12 without the private key, use nokey option.)
 | 
						|
Missing key expected at: $key_in"
 | 
						|
		else
 | 
						|
			pkcs_opts="$pkcs_opts -nokeys"
 | 
						|
		fi
 | 
						|
 | 
						|
		# export the p12:
 | 
						|
		# shellcheck disable=SC2086
 | 
						|
		easyrsa_openssl pkcs12 -in "$crt_in" -inkey "$key_in" -export \
 | 
						|
			-out "$pkcs_out" $pkcs_opts ${EASYRSA_PASSIN:+-passin "$EASYRSA_PASSIN"} ${EASYRSA_PASSOUT:+-passout "$EASYRSA_PASSOUT"} || die "\
 | 
						|
Export of p12 failed: see above for related openssl errors."
 | 
						|
	;;
 | 
						|
	p7)
 | 
						|
		pkcs_out="$EASYRSA_PKI/issued/$short_name.p7b"
 | 
						|
 | 
						|
		# export the p7:
 | 
						|
		# shellcheck disable=SC2086
 | 
						|
		easyrsa_openssl crl2pkcs7 -nocrl -certfile "$crt_in" \
 | 
						|
			-out "$pkcs_out" $pkcs_opts ${EASYRSA_PASSIN:+-passin "$EASYRSA_PASSIN"} ${EASYRSA_PASSOUT:+-passout "$EASYRSA_PASSOUT"} || die "\
 | 
						|
Export of p7 failed: see above for related openssl errors."
 | 
						|
	;;
 | 
						|
	p8)
 | 
						|
		if [ -z $want_pass ]; then
 | 
						|
			pkcs_opts="-nocrypt"
 | 
						|
		else
 | 
						|
			pkcs_opts=""
 | 
						|
		fi
 | 
						|
		pkcs_out="$EASYRSA_PKI/private/$short_name.p8"
 | 
						|
 | 
						|
		# export the p8:
 | 
						|
		# shellcheck disable=SC2086
 | 
						|
		easyrsa_openssl pkcs8 -in "$key_in" -topk8 \
 | 
						|
			-out "$pkcs_out" $pkcs_opts ${EASYRSA_PASSIN:+-passin "$EASYRSA_PASSIN"} ${EASYRSA_PASSOUT:+-passout "$EASYRSA_PASSOUT"} || die "\
 | 
						|
Export of p8 failed: see above for related openssl errors."
 | 
						|
      ;;
 | 
						|
esac
 | 
						|
 | 
						|
	notice "\
 | 
						|
Successful export of $pkcs_type file. Your exported file is at the following
 | 
						|
location: $pkcs_out
 | 
						|
"
 | 
						|
	return 0
 | 
						|
} # => export_pkcs()
 | 
						|
 | 
						|
# set-pass backend
 | 
						|
set_pass() {
 | 
						|
	verify_pki_init
 | 
						|
 | 
						|
	# key type, supplied internally from frontend command call (rsa/ec)
 | 
						|
	key_type="$1"
 | 
						|
 | 
						|
	# values supplied by the user:
 | 
						|
	raw_file="$2"
 | 
						|
	file="$EASYRSA_PKI/private/$raw_file.key"
 | 
						|
	[ -n "$raw_file" ] || die "\
 | 
						|
Missing argument to 'set-$key_type-pass' command: no name/file supplied.
 | 
						|
See help output for usage details."
 | 
						|
 | 
						|
	# parse command options
 | 
						|
	shift 2
 | 
						|
	crypto="-aes256"
 | 
						|
	while [ -n "$1" ]; do
 | 
						|
		case "$1" in
 | 
						|
			nopass)	crypto="" ;;
 | 
						|
			file)	file="$raw_file" ;;
 | 
						|
			*)	warn "Ignoring unknown command option: '$1'" ;;
 | 
						|
		esac
 | 
						|
		shift
 | 
						|
	done
 | 
						|
 | 
						|
	[ -f "$file" ] || die "\
 | 
						|
Missing private key: expected to find the private key component at:
 | 
						|
$file"
 | 
						|
 | 
						|
	notice "\
 | 
						|
If the key is currently encrypted you must supply the decryption passphrase.
 | 
						|
${crypto:+You will then enter a new PEM passphrase for this key.$NL}"
 | 
						|
 | 
						|
	out_key_tmp="$(easyrsa_mktemp)" || die "Failed to create temporary file"
 | 
						|
	easyrsa_openssl "$key_type" -in "$file" -out "$out_key_tmp" $crypto ${EASYRSA_PASSIN:+-passin "$EASYRSA_PASSIN"} ${EASYRSA_PASSOUT:+-passout "$EASYRSA_PASSOUT"} || die "\
 | 
						|
Failed to change the private key passphrase. See above for possible openssl
 | 
						|
error messages."
 | 
						|
 | 
						|
	mv "$out_key_tmp" "$file" || die "\
 | 
						|
Failed to change the private key passphrase. See above for error messages."
 | 
						|
 | 
						|
	notice "Key passphrase successfully changed"
 | 
						|
 | 
						|
	return 0
 | 
						|
} # => set_pass()
 | 
						|
 | 
						|
# update-db backend
 | 
						|
update_db() {
 | 
						|
	verify_ca_init
 | 
						|
 | 
						|
	easyrsa_openssl ca -utf8 -updatedb ${EASYRSA_PASSIN:+-passin "$EASYRSA_PASSIN"} || die "\
 | 
						|
Failed to perform update-db: see above for related openssl errors."
 | 
						|
	return 0
 | 
						|
} # => update_db()
 | 
						|
 | 
						|
display_san() {
 | 
						|
	format="$1" path="$2"
 | 
						|
 | 
						|
	echo "$EASYRSA_EXTRA_EXTS" | grep -q subjectAltName
 | 
						|
 | 
						|
	if [ $? -eq 0 ]; then
 | 
						|
		print "$(echo "$EASYRSA_EXTRA_EXTS" | grep subjectAltName | sed 's/^\s*subjectAltName\s*=\s*//')"
 | 
						|
	else
 | 
						|
		san=$(
 | 
						|
			"$EASYRSA_OPENSSL" "$format" -in "$path" -noout -text |
 | 
						|
			sed -n "/X509v3 Subject Alternative Name:/{n;s/ //g;s/IPAddress:/IP:/g;s/RegisteredID/RID/;p;}"
 | 
						|
			)
 | 
						|
 | 
						|
		[ -n "$san" ] && print "$san"
 | 
						|
	fi
 | 
						|
}
 | 
						|
 | 
						|
# display cert DN info on a req/X509, passed by full pathname
 | 
						|
display_dn() {
 | 
						|
	format="$1" path="$2"
 | 
						|
	print "$("$EASYRSA_OPENSSL" "$format" -in "$path" -noout -subject -nameopt multiline)"
 | 
						|
	san=$(display_san "$1" "$2")
 | 
						|
	if [ -n "$san" ]; then
 | 
						|
		print ""
 | 
						|
		print "X509v3 Subject Alternative Name:"
 | 
						|
		print "    $san"
 | 
						|
	fi
 | 
						|
 | 
						|
} # => display_dn()
 | 
						|
 | 
						|
# generate default SAN from req/X509, passed by full pathname
 | 
						|
default_server_san() {
 | 
						|
	path="$1"
 | 
						|
	cn=$(
 | 
						|
		easyrsa_openssl req -in "$path" -noout -subject -nameopt sep_multiline |
 | 
						|
		awk -F'=' '/^  *CN=/{print $2}'
 | 
						|
		)
 | 
						|
	echo "$cn" | grep -E -q '^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$'
 | 
						|
	#shellcheck disable=SC2181
 | 
						|
	if [ $? -eq 0 ]; then
 | 
						|
		print "subjectAltName = IP:$cn"
 | 
						|
	else
 | 
						|
		print "subjectAltName = DNS:$cn"
 | 
						|
	fi
 | 
						|
} # => default_server_san()
 | 
						|
 | 
						|
# verify a file seems to be a valid req/X509
 | 
						|
verify_file() {
 | 
						|
	format="$1" 
 | 
						|
	path="$2"
 | 
						|
	easyrsa_openssl "$format" -in "$path" -noout 2>/dev/null || return 1
 | 
						|
	return 0
 | 
						|
} # => verify_file()
 | 
						|
 | 
						|
# show-* command backend
 | 
						|
# Prints req/cert details in a readable format
 | 
						|
show() {
 | 
						|
	type="$1" 
 | 
						|
	name="$2" 
 | 
						|
	in_file=""
 | 
						|
	format=""
 | 
						|
	[ -n "$name" ] || die "\
 | 
						|
Missing expected filename_base argument.
 | 
						|
Run easyrsa without commands for usage help."
 | 
						|
	shift 2
 | 
						|
 | 
						|
	# opts support
 | 
						|
	opts="-${type}opt no_pubkey,no_sigdump"
 | 
						|
	while [ -n "$1" ]; do
 | 
						|
		case "$1" in
 | 
						|
			full) 
 | 
						|
				opts=""
 | 
						|
				;;
 | 
						|
			*) 
 | 
						|
				warn "Ignoring unknown command option: '$1'" 
 | 
						|
				;;
 | 
						|
		esac
 | 
						|
		shift
 | 
						|
	done
 | 
						|
 | 
						|
	# Determine cert/req type
 | 
						|
	if [ "$type" = "cert" ]; then
 | 
						|
		verify_ca_init
 | 
						|
		in_file="$EASYRSA_PKI/issued/${name}.crt"
 | 
						|
		format="x509"
 | 
						|
	else
 | 
						|
		verify_pki_init
 | 
						|
		in_file="$EASYRSA_PKI/reqs/${name}.req"
 | 
						|
		format="req"
 | 
						|
	fi
 | 
						|
 | 
						|
	# Verify file exists and is of the correct type
 | 
						|
	[ -f "$in_file" ] || die "\
 | 
						|
No such $type file with a basename of '$name' is present.
 | 
						|
Expected to find this file at:
 | 
						|
$in_file"
 | 
						|
	verify_file $format "$in_file" || die "\
 | 
						|
This file is not a valid $type file:
 | 
						|
$in_file"
 | 
						|
 | 
						|
	notice "\
 | 
						|
Showing $type details for '$name'.
 | 
						|
This file is stored at:
 | 
						|
$in_file
 | 
						|
"
 | 
						|
	easyrsa_openssl $format -in "$in_file" -noout -text\
 | 
						|
		-nameopt multiline $opts || die "\
 | 
						|
OpenSSL failure to process the input"
 | 
						|
} # => show()
 | 
						|
 | 
						|
# show-ca command backend
 | 
						|
# Prints CA cert details in a readable format
 | 
						|
show_ca() {
 | 
						|
	# opts support
 | 
						|
	opts="-certopt no_pubkey,no_sigdump"
 | 
						|
	while [ -n "$1" ]; do
 | 
						|
		case "$1" in
 | 
						|
			full) opts= ;;
 | 
						|
			*) warn "Ignoring unknown command option: '$1'" ;;
 | 
						|
		esac
 | 
						|
		shift
 | 
						|
	done
 | 
						|
 | 
						|
	verify_ca_init
 | 
						|
	in_file="$EASYRSA_PKI/ca.crt"
 | 
						|
	format="x509"
 | 
						|
 | 
						|
	# Verify file exists and is of the correct type
 | 
						|
	[ -f "$in_file" ] || die "\
 | 
						|
No such $type file with a basename of '$name' is present.
 | 
						|
Expected to find this file at:
 | 
						|
$in_file"
 | 
						|
	verify_file $format "$in_file" || die "\
 | 
						|
This file is not a valid $type file:
 | 
						|
$in_file"
 | 
						|
 | 
						|
	notice "\
 | 
						|
Showing $type details for 'ca'.
 | 
						|
This file is stored at:
 | 
						|
$in_file
 | 
						|
"
 | 
						|
	easyrsa_openssl $format -in "$in_file" -noout -text\
 | 
						|
		-nameopt multiline $opts || die "\
 | 
						|
OpenSSL failure to process the input"
 | 
						|
} # => show_ca()
 | 
						|
 | 
						|
# vars setup
 | 
						|
# Here sourcing of 'vars' if present occurs. If not present, defaults are used
 | 
						|
# to support running without a sourced config format
 | 
						|
vars_setup() {
 | 
						|
	# Try to locate a 'vars' file in order of location preference.
 | 
						|
	# If one is found, source it
 | 
						|
	vars=
 | 
						|
 | 
						|
	# set up program path
 | 
						|
	prog_file="$0"
 | 
						|
	prog_file2="$(which -- "$prog_file" 2>/dev/null)" && prog_file="$prog_file2"
 | 
						|
	prog_file2="$(readlink -f "$prog_file" 2>/dev/null)" && prog_file="$prog_file2"
 | 
						|
	prog_dir="${prog_file%/*}"
 | 
						|
	prog_vars="${prog_dir}/vars"
 | 
						|
	# set up PKI path
 | 
						|
	pki_vars="${EASYRSA_PKI:-$PWD/pki}/vars"
 | 
						|
 | 
						|
	# command-line path:
 | 
						|
	if [ ! -z "$EASYRSA_VARS_FILE" ]; then
 | 
						|
	  if [ ! -f "$EASYRSA_VARS_FILE" ]; then
 | 
						|
		  # If the --vars option does not point to a file, show helpful error.
 | 
						|
			die "The file '$EASYRSA_VARS_FILE' was not found."
 | 
						|
		fi
 | 
						|
		vars="$EASYRSA_VARS_FILE"
 | 
						|
	# PKI location, if present:
 | 
						|
	elif [ -f "$pki_vars" ]; then
 | 
						|
		vars="$pki_vars"
 | 
						|
	# EASYRSA, if defined:
 | 
						|
	elif [ -n "$EASYRSA" ] && [ -f "$EASYRSA/vars" ]; then
 | 
						|
		vars="$EASYRSA/vars"
 | 
						|
	# program location:
 | 
						|
	elif [ -f "$prog_vars" ]; then
 | 
						|
		vars="$prog_vars"
 | 
						|
	fi
 | 
						|
	
 | 
						|
	# If a vars file was located, source it
 | 
						|
	# If $EASYRSA_NO_VARS is defined (not blank) this is skipped
 | 
						|
	if [ -z "$EASYRSA_NO_VARS" ] && [ -n "$vars" ]; then
 | 
						|
		if grep -Eq 'EASYRSA_PASSIN|EASYRSA_PASSOUT' "$vars"; then
 | 
						|
			die "\
 | 
						|
Variable EASYRSA_PASSIN or EASYRSA_PASSOUT has been found in the configuration \
 | 
						|
file. Storing sensitive information in the configuration file is not \
 | 
						|
recommended - please remove it from there before continuing."
 | 
						|
		fi
 | 
						|
		#shellcheck disable=SC2034
 | 
						|
		EASYRSA_CALLER=1 
 | 
						|
		# shellcheck disable=SC1090
 | 
						|
		. "$vars"
 | 
						|
		notice "\
 | 
						|
Note: using Easy-RSA configuration from: $vars"
 | 
						|
	fi
 | 
						|
	
 | 
						|
	# Set defaults, preferring existing env-vars if present
 | 
						|
	set_var EASYRSA		"$prog_dir"
 | 
						|
	set_var EASYRSA_OPENSSL	openssl
 | 
						|
	set_var EASYRSA_PKI	"$PWD/pki"
 | 
						|
	set_var EASYRSA_DN	cn_only
 | 
						|
	set_var EASYRSA_REQ_COUNTRY	"US"
 | 
						|
	set_var EASYRSA_REQ_PROVINCE	"California"
 | 
						|
	set_var EASYRSA_REQ_CITY	"San Francisco"
 | 
						|
	set_var EASYRSA_REQ_ORG		"Copyleft Certificate Co"
 | 
						|
	set_var EASYRSA_REQ_EMAIL	me@example.net
 | 
						|
	set_var EASYRSA_REQ_OU		"My Organizational Unit"
 | 
						|
	set_var EASYRSA_ALGO		rsa
 | 
						|
	set_var EASYRSA_KEY_SIZE	2048
 | 
						|
	set_var EASYRSA_CURVE		secp384r1
 | 
						|
	set_var EASYRSA_EC_DIR		"$EASYRSA_PKI/ecparams"
 | 
						|
	set_var EASYRSA_CA_EXPIRE	3650
 | 
						|
	set_var EASYRSA_CERT_EXPIRE	825 # new default of 36 months	
 | 
						|
	set_var EASYRSA_CERT_RENEW	30
 | 
						|
	set_var EASYRSA_CRL_DAYS	180
 | 
						|
	set_var EASYRSA_NS_SUPPORT	no
 | 
						|
	set_var EASYRSA_NS_COMMENT	"Easy-RSA (3.0.8) Generated Certificate"
 | 
						|
	set_var EASYRSA_TEMP_DIR	"$EASYRSA_PKI"
 | 
						|
	set_var EASYRSA_REQ_CN		ChangeMe
 | 
						|
	set_var EASYRSA_DIGEST		sha256
 | 
						|
	set_var EASYRSA_SSL_CONF	"$EASYRSA_PKI/openssl-easyrsa.cnf"
 | 
						|
	set_var EASYRSA_SAFE_CONF	"$EASYRSA_PKI/safessl-easyrsa.cnf"
 | 
						|
	set_var EASYRSA_KDC_REALM	"CHANGEME.EXAMPLE.COM"
 | 
						|
 | 
						|
	# Same as above for the x509-types extensions dir
 | 
						|
	if [ -d "$EASYRSA_PKI/x509-types" ]; then
 | 
						|
		set_var EASYRSA_EXT_DIR		"$EASYRSA_PKI/x509-types"
 | 
						|
	else	
 | 
						|
		#TODO: This should be removed.  Not really suitable for packaging.
 | 
						|
		set_var EASYRSA_EXT_DIR		"$EASYRSA/x509-types"
 | 
						|
	fi
 | 
						|
 | 
						|
	# EASYRSA_ALGO_PARAMS must be set depending on selected algo
 | 
						|
	if [ "ec" = "$EASYRSA_ALGO" ]; then
 | 
						|
		EASYRSA_ALGO_PARAMS="$EASYRSA_EC_DIR/${EASYRSA_CURVE}.pem"
 | 
						|
	elif [ "rsa" = "$EASYRSA_ALGO" ]; then
 | 
						|
		EASYRSA_ALGO_PARAMS="${EASYRSA_KEY_SIZE}"
 | 
						|
	elif [ "ed" != "$EASYRSA_ALGO" ]; then
 | 
						|
		die "Alg '$EASYRSA_ALGO' is invalid: must be 'rsa', 'ec' or 'ed' "
 | 
						|
	fi
 | 
						|
 | 
						|
	# Assign value to $EASYRSA_TEMP_DIR_session and work around Windows mktemp bug when parent dir is missing
 | 
						|
	if [ -z "$EASYRSA_TEMP_DIR_session" ]; then
 | 
						|
		if [ -d "$EASYRSA_TEMP_DIR" ]; then
 | 
						|
			EASYRSA_TEMP_DIR_session="$(mktemp -du "$EASYRSA_TEMP_DIR/easy-rsa-$$.XXXXXX")"
 | 
						|
		else
 | 
						|
			# If the directory does not exist then we have not run init-pki
 | 
						|
			mkdir -p "$EASYRSA_TEMP_DIR" || die "Cannot create $EASYRSA_TEMP_DIR (permission?)"
 | 
						|
			EASYRSA_TEMP_DIR_session="$(mktemp -du "$EASYRSA_TEMP_DIR/easy-rsa-$$.XXXXXX")"
 | 
						|
			rm -rf "$EASYRSA_TEMP_DIR"
 | 
						|
		fi
 | 
						|
	fi
 | 
						|
 | 
						|
	# Setting OPENSSL_CONF prevents bogus warnings (especially useful on win32)
 | 
						|
	export OPENSSL_CONF="$EASYRSA_SAFE_CONF"
 | 
						|
 | 
						|
	# Upgrade to 306: Create $EASYRSA_SSL_CONF if it does not exist but only if $EASYRSA_PKI exists.
 | 
						|
	if [ ! -f "$EASYRSA_SSL_CONF" ] && [ -f "$EASYRSA/openssl-easyrsa.cnf" ] && [ -d "$EASYRSA_PKI" ];
 | 
						|
	then
 | 
						|
		cp "$EASYRSA/openssl-easyrsa.cnf" "$EASYRSA_SSL_CONF"
 | 
						|
		easyrsa_openssl makesafeconf
 | 
						|
	fi
 | 
						|
 | 
						|
} # vars_setup()
 | 
						|
 | 
						|
# variable assignment by indirection when undefined; merely exports
 | 
						|
# the variable when it is already defined (even if currently null)
 | 
						|
# Sets $1 as the value contained in $2 and exports (may be blank)
 | 
						|
set_var() {
 | 
						|
	var=$1
 | 
						|
	shift
 | 
						|
	value="$*"
 | 
						|
	eval "export $var=\"\${$var-$value}\""
 | 
						|
} #=> set_var()
 | 
						|
 | 
						|
 | 
						|
############################################################################
 | 
						|
# Upgrade v2 PKI to v3 PKI
 | 
						|
 | 
						|
# You can report problems on the normal openvpn support channels:
 | 
						|
# --------------------------------------------------------------------------
 | 
						|
#   1. The Openvpn Forum: https://forums.openvpn.net/viewforum.php?f=31
 | 
						|
#   2. The #easyrsa IRC channel at freenode
 | 
						|
#   3. Info: https://community.openvpn.net/openvpn/wiki/easyrsa-upgrade
 | 
						|
# --------------------------------------------------------------------------
 | 
						|
#
 | 
						|
 | 
						|
up23_fail_upgrade ()
 | 
						|
{
 | 
						|
	# Replace die()
 | 
						|
	unset EASYRSA_BATCH
 | 
						|
	notice "
 | 
						|
============================================================================
 | 
						|
The update has failed but NOTHING has been lost.
 | 
						|
 | 
						|
ERROR: $1
 | 
						|
----------------------------------------------------------------------------
 | 
						|
 | 
						|
Further info:
 | 
						|
* https://community.openvpn.net/openvpn/wiki/easyrsa-upgrade#ersa-up23-fails
 | 
						|
 | 
						|
Easyrsa3 upgrade FAILED
 | 
						|
============================================================================
 | 
						|
"
 | 
						|
	exit 9
 | 
						|
} #=> up23_fail_upgrade ()
 | 
						|
 | 
						|
up23_verbose ()
 | 
						|
{
 | 
						|
	[ "$VERBOSE" ] || return 0
 | 
						|
	printf "%s\n" "$1"
 | 
						|
} #=> up23_verbose ()
 | 
						|
 | 
						|
up23_verify_new_pki ()
 | 
						|
{
 | 
						|
	# Fail now, before any changes are made
 | 
						|
 | 
						|
	up23_verbose "> Verify DEFAULT NEW PKI does not exist .."
 | 
						|
	EASYRSA_NEW_PKI="$EASYRSA/pki"
 | 
						|
	[ -d "$EASYRSA_NEW_PKI" ] \
 | 
						|
	&& up23_fail_upgrade "DEFAULT NEW PKI exists: $EASYRSA_NEW_PKI"
 | 
						|
 | 
						|
	up23_verbose "> Verify VERY-SAFE-PKI does not exist .."
 | 
						|
	EASYRSA_SAFE_PKI="$EASYRSA/VERY-SAFE-PKI"
 | 
						|
	[ -d "$EASYRSA_SAFE_PKI" ] \
 | 
						|
	&& up23_fail_upgrade "VERY-SAFE-PKI exists: $EASYRSA_SAFE_PKI"
 | 
						|
 | 
						|
	up23_verbose "> Verify openssl-easyrsa.cnf does exist .."
 | 
						|
	EASYRSA_SSL_CNFFILE="$EASYRSA/openssl-easyrsa.cnf"
 | 
						|
	[ -f "$EASYRSA_SSL_CNFFILE" ] \
 | 
						|
	|| up23_fail_upgrade "cannot find $EASYRSA_SSL_CNFFILE"
 | 
						|
 | 
						|
	up23_verbose "> Verify vars.example does exist .."
 | 
						|
	EASYRSA_VARSV3_EXMP="$EASYRSA/vars.example"
 | 
						|
	[ -f "$EASYRSA_VARSV3_EXMP" ] \
 | 
						|
	|| up23_fail_upgrade "cannot find $EASYRSA_VARSV3_EXMP"
 | 
						|
 | 
						|
	up23_verbose "> OK"
 | 
						|
	up23_verbose "  Initial dirs & files are in a workable state."
 | 
						|
} #=> up23_verify_new_pki ()
 | 
						|
 | 
						|
up23_verify_current_pki ()
 | 
						|
{
 | 
						|
	up23_verbose "> Verify CURRENT PKI vars .."
 | 
						|
 | 
						|
	# This can probably be improved
 | 
						|
	EASYRSA_NO_REM="$(grep '^set ' "$EASYRSA_VER2_VARSFILE")"
 | 
						|
 | 
						|
	# This list may not be complete
 | 
						|
	# Not required: DH_KEY_SIZE PKCS11_MODULE_PATH PKCS11_PIN
 | 
						|
	for i in KEY_DIR KEY_SIZE KEY_COUNTRY KEY_PROVINCE \
 | 
						|
	KEY_CITY KEY_ORG KEY_EMAIL KEY_CN KEY_NAME KEY_OU
 | 
						|
	do
 | 
						|
		# Effectively, source the v2 vars file
 | 
						|
		UNIQUE="set $i"
 | 
						|
		KEY_grep="$(printf "%s\n" "$EASYRSA_NO_REM" | grep "$UNIQUE")"
 | 
						|
		KEY_value="${KEY_grep##*=}"
 | 
						|
		set_var $i "$KEY_value"
 | 
						|
	done
 | 
						|
 | 
						|
	[ -d "$KEY_DIR" ] || up23_fail_upgrade "Cannot find CURRENT PKI KEY_DIR: $KEY_DIR"
 | 
						|
 | 
						|
	up23_verbose "> OK"
 | 
						|
	up23_verbose "  Current CURRENT PKI vars uses PKI in: $KEY_DIR"
 | 
						|
} #=> up23_verify_current_pki ()
 | 
						|
 | 
						|
up23_verify_current_ca ()
 | 
						|
{
 | 
						|
	up23_verbose "> Find CA .."
 | 
						|
	# $KEY_DIR is assigned in up23_verify_current_pki ()
 | 
						|
	[ -f "$KEY_DIR/ca.crt" ] \
 | 
						|
	|| up23_fail_upgrade "Cannot find current ca.crt: $KEY_DIR/ca.crt"
 | 
						|
	up23_verbose "> OK"
 | 
						|
 | 
						|
	# If CA is already verified then return
 | 
						|
	in_file="$KEY_DIR/ca.crt"
 | 
						|
	[ "$CURRENT_CA_IS_VERIFIED" = "$in_file" ] && return 0
 | 
						|
	format="x509"
 | 
						|
 | 
						|
	# Current CA is unverified
 | 
						|
	# Extract the current CA details
 | 
						|
	CA_SUBJECT="$(easyrsa_openssl $format -in "$in_file" -subject -noout -nameopt multiline)"
 | 
						|
 | 
						|
	# Extract individual elements
 | 
						|
	CA_countryName="$(printf "%s\n" "$CA_SUBJECT" \
 | 
						|
	| grep countryName | sed "s\`^.*=\ \`\`g")"
 | 
						|
	CA_stateOrProvinceName="$(printf "%s\n" "$CA_SUBJECT" \
 | 
						|
	| grep stateOrProvinceName | sed "s\`^.*=\ \`\`g")"
 | 
						|
	CA_localityName="$(printf "%s\n" "$CA_SUBJECT" \
 | 
						|
	| grep localityName | sed "s\`^.*=\ \`\`g")"
 | 
						|
	CA_organizationName="$(printf "%s\n" "$CA_SUBJECT" \
 | 
						|
	| grep organizationName | sed "s\`^.*=\ \`\`g")"
 | 
						|
	CA_organizationalUnitName="$(printf "%s\n" "$CA_SUBJECT" \
 | 
						|
	| grep organizationalUnitName | sed "s\`^.*=\ \`\`g")"
 | 
						|
	CA_emailAddress="$(printf "%s\n" "$CA_SUBJECT" \
 | 
						|
	| grep emailAddress | sed "s\`^.*=\ \`\`g")"
 | 
						|
 | 
						|
	# Match the current CA elements to the vars file settings
 | 
						|
	CA_vars_match=1
 | 
						|
	[ "$CA_countryName" = "$KEY_COUNTRY" ] || CA_vars_match=0
 | 
						|
	[ "$CA_stateOrProvinceName" = "$KEY_PROVINCE" ] || CA_vars_match=0
 | 
						|
	[ "$CA_localityName" = "$KEY_CITY" ] || CA_vars_match=0
 | 
						|
	[ "$CA_organizationName" = "$KEY_ORG" ] || CA_vars_match=0
 | 
						|
	[ "$CA_organizationalUnitName" = "$KEY_OU" ] || CA_vars_match=0
 | 
						|
	[ "$CA_emailAddress" = "$KEY_EMAIL" ] || CA_vars_match=0
 | 
						|
 | 
						|
	if [ "$CA_vars_match" -eq 1 ]
 | 
						|
	then
 | 
						|
		CURRENT_CA_IS_VERIFIED="partially"
 | 
						|
	else
 | 
						|
		up23_fail_upgrade "CA certificate does not match vars file settings"
 | 
						|
	fi
 | 
						|
 | 
						|
	opts="-certopt no_pubkey,no_sigdump"
 | 
						|
	if [ ! "$EASYRSA_BATCH" ]
 | 
						|
	then
 | 
						|
		up23_show_current_ca
 | 
						|
	elif [ "$VERBOSE" ]
 | 
						|
	then
 | 
						|
		up23_show_current_ca
 | 
						|
	fi
 | 
						|
	confirm "* Confirm CA shown above is correct: " "yes" \
 | 
						|
	"Found current CA at: $KEY_DIR/ca.crt"
 | 
						|
	CURRENT_CA_IS_VERIFIED="$in_file"
 | 
						|
} #=> up23_verify_current_ca ()
 | 
						|
 | 
						|
up23_show_current_ca ()
 | 
						|
{
 | 
						|
	printf "%s\n" "-------------------------------------------------------------------------"
 | 
						|
	# $opts is always set here
 | 
						|
	# shellcheck disable=SC2086
 | 
						|
	easyrsa_openssl $format -in "$in_file" -noout -text\
 | 
						|
	-nameopt multiline $opts || die "\
 | 
						|
	OpenSSL failure to process the input CA certificate: $in_file"
 | 
						|
	printf "%s\n" "-------------------------------------------------------------------------"
 | 
						|
} #=> up23_show_current_ca ()
 | 
						|
 | 
						|
up23_backup_current_pki ()
 | 
						|
{
 | 
						|
	up23_verbose "> Backup current PKI .."
 | 
						|
 | 
						|
	mkdir -p "$EASYRSA_SAFE_PKI" \
 | 
						|
	|| up23_fail_upgrade "Failed to create safe PKI dir: $EASYRSA_SAFE_PKI"
 | 
						|
 | 
						|
	cp -r "$KEY_DIR" "$EASYRSA_SAFE_PKI" \
 | 
						|
	|| up23_fail_upgrade "Failed to copy $KEY_DIR to $EASYRSA_SAFE_PKI"
 | 
						|
 | 
						|
	# EASYRSA_VER2_VARSFILE is either version 2 *nix ./vars or Win vars.bat
 | 
						|
	cp "$EASYRSA_VER2_VARSFILE" "$EASYRSA_SAFE_PKI" \
 | 
						|
	|| up23_fail_upgrade "Failed to copy $EASYRSA_VER2_VARSFILE to EASYRSA_SAFE_PKI"
 | 
						|
 | 
						|
	up23_verbose "> OK"
 | 
						|
	up23_verbose "  Current PKI backup created in: $EASYRSA_SAFE_PKI"
 | 
						|
} #=> up23_backup_current_pki ()
 | 
						|
 | 
						|
up23_create_new_pki ()
 | 
						|
{
 | 
						|
	# Dirs: renewed and revoked are created when used.
 | 
						|
	up23_verbose "> Create NEW PKI .."
 | 
						|
	up23_verbose ">> Create NEW PKI dirs .."
 | 
						|
	for i in private reqs issued certs_by_serial
 | 
						|
	do
 | 
						|
		mkdir -p "$EASYRSA_PKI/$i" \
 | 
						|
		|| up23_fail_upgrade "Failed to Create NEW PKI dir: $EASYRSA_PKI/$i"
 | 
						|
	done
 | 
						|
	up23_verbose ">> OK"
 | 
						|
 | 
						|
	up23_verbose ">> Copy database to NEW PKI .."
 | 
						|
	# Failure for these is not optional
 | 
						|
	# Files ignored: index.txt.old serial.old
 | 
						|
	for i in index.txt serial ca.crt index.txt.attr
 | 
						|
	do
 | 
						|
		cp "$KEY_DIR/$i" "$EASYRSA_PKI" \
 | 
						|
		|| up23_fail_upgrade "Failed to copy $KEY_DIR/$i to $EASYRSA_PKI"
 | 
						|
	done
 | 
						|
	up23_verbose ">> OK"
 | 
						|
 | 
						|
	up23_verbose ">> Copy current PKI to NEW PKI .."
 | 
						|
	for i in "csr.reqs" "pem.certs_by_serial" "crt.issued" "key.private" \
 | 
						|
	"p12.private" "p8.private" "p7b.issued"
 | 
						|
	do
 | 
						|
		FILE_EXT="${i%%.*}"
 | 
						|
		DEST_DIR="${i##*.}"
 | 
						|
		if ls "$KEY_DIR/"*".$FILE_EXT" > /dev/null 2>&1; then
 | 
						|
			cp "$KEY_DIR/"*".$FILE_EXT" "$EASYRSA_PKI/$DEST_DIR" \
 | 
						|
			|| up23_fail_upgrade "Failed to copy .$FILE_EXT"
 | 
						|
		else
 | 
						|
			up23_verbose "   Note: No .$FILE_EXT files found"
 | 
						|
		fi
 | 
						|
	done
 | 
						|
	up23_verbose ">> OK"
 | 
						|
	up23_verbose "> OK"
 | 
						|
 | 
						|
	# Todo: CRL - Or generate a new CRL on completion
 | 
						|
	up23_verbose "  New PKI created in: $EASYRSA_PKI"
 | 
						|
} #=> up23_create_new_pki ()
 | 
						|
 | 
						|
up23_upgrade_ca ()
 | 
						|
{
 | 
						|
	[ -d "$EASYRSA_PKI" ] || return 0
 | 
						|
	up23_verbose "> Confirm that index.txt.attr exists and 'unique_subject = no'"
 | 
						|
	if [ -f "$EASYRSA_PKI/index.txt.attr" ]
 | 
						|
	then
 | 
						|
		if grep -q 'unique_subject = no' "$EASYRSA_PKI/index.txt.attr"
 | 
						|
		then
 | 
						|
			# If index.txt.attr exists and "unique_suject = no" then do nothing
 | 
						|
			return 0
 | 
						|
		fi
 | 
						|
	else
 | 
						|
		# If index.txt.attr does not exists then do nothing
 | 
						|
		return 0
 | 
						|
	fi
 | 
						|
 | 
						|
	# Otherwise this is required for all easyrsa v3
 | 
						|
	#confirm "Set 'unique_subject = no' in index.txt.attr for your current CA: " \
 | 
						|
	#"yes" "This version of easyrsa requires that 'unique_subject = no' is set correctly"
 | 
						|
	
 | 
						|
	printf "%s\n" "unique_subject = no" > "$EASYRSA_PKI/index.txt.attr"
 | 
						|
	up23_verbose "> OK"
 | 
						|
	up23_verbose "  Upgraded index.txt.attr to v306+"
 | 
						|
} #=> up23_upgrade_index_txt_attr ()
 | 
						|
 | 
						|
up23_create_openssl_cnf ()
 | 
						|
{
 | 
						|
	up23_verbose "> OpenSSL config .."
 | 
						|
	EASYRSA_PKI_SSL_CNFFILE="$EASYRSA_PKI/openssl-easyrsa.cnf"
 | 
						|
	EASYRSA_PKI_SAFE_CNFFILE="$EASYRSA_PKI/safessl-easyrsa.cnf"
 | 
						|
	cp "$EASYRSA_SSL_CNFFILE" "$EASYRSA_PKI_SSL_CNFFILE" \
 | 
						|
	|| up23_fail_upgrade "create $EASYRSA_PKI_SSL_CNFFILE"
 | 
						|
	up23_verbose "> OK"
 | 
						|
	up23_verbose "  New OpenSSL config file created in: $EASYRSA_PKI_SSL_CNFFILE"
 | 
						|
 | 
						|
	# Create $EASYRSA_PKI/safessl-easyrsa.cnf
 | 
						|
	easyrsa_openssl makesafeconf
 | 
						|
	if [ -f "$EASYRSA_PKI_SAFE_CNFFILE" ]
 | 
						|
	then
 | 
						|
		up23_verbose "  New SafeSSL config file created in: $EASYRSA_PKI_SAFE_CNFFILE"
 | 
						|
	else
 | 
						|
		up23_verbose "  FAILED to create New SafeSSL config file in: $EASYRSA_PKI_SAFE_CNFFILE"
 | 
						|
	fi
 | 
						|
} #=> up23_create_openssl_cnf ()
 | 
						|
 | 
						|
up23_move_easyrsa2_programs ()
 | 
						|
{
 | 
						|
	# These files may not exist here
 | 
						|
	up23_verbose "> Move easyrsa2 programs to SAFE PKI .."
 | 
						|
	for i in build-ca build-dh build-inter build-key build-key-pass \
 | 
						|
	build-key-pkcs12 build-key-server build-req build-req-pass \
 | 
						|
	clean-all inherit-inter list-crl pkitool revoke-full sign-req \
 | 
						|
	whichopensslcnf build-ca-pass build-key-server-pass init-config \
 | 
						|
	make-crl revoke-crt openssl-0.9.6.cnf openssl-0.9.8.cnf \
 | 
						|
	openssl-1.0.0.cnf openssl.cnf README.txt index.txt.start \
 | 
						|
	vars.bat.sample serial.start
 | 
						|
	do
 | 
						|
		# Although unlikely, both files could exist
 | 
						|
		# EG: ./build-ca and ./build-ca.bat
 | 
						|
		NIX_FILE="$EASYRSA/$i"
 | 
						|
		WIN_FILE="$EASYRSA/$i.bat"
 | 
						|
		if [ -f "$NIX_FILE" ]
 | 
						|
		then
 | 
						|
			cp "$NIX_FILE" "$EASYRSA_SAFE_PKI" \
 | 
						|
			|| up23_fail_upgrade "copy $NIX_FILE $EASYRSA_SAFE_PKI"
 | 
						|
		fi
 | 
						|
 | 
						|
		if [ -f "$WIN_FILE" ]
 | 
						|
		then
 | 
						|
			cp "$WIN_FILE" "$EASYRSA_SAFE_PKI" \
 | 
						|
			|| up23_fail_upgrade "copy $WIN_FILE $EASYRSA_SAFE_PKI"
 | 
						|
		fi
 | 
						|
 | 
						|
		if [ ! -f "$NIX_FILE" ] && [ ! -f "$WIN_FILE" ]
 | 
						|
		then
 | 
						|
			up23_verbose "File does not exist, ignoring: $i(.bat)"
 | 
						|
		fi
 | 
						|
 | 
						|
	# These files are not removed on TEST run
 | 
						|
	[ "$NOSAVE" -eq 1  ] && rm -f "$NIX_FILE" "$WIN_FILE"
 | 
						|
	done
 | 
						|
 | 
						|
	up23_verbose "> OK"
 | 
						|
	up23_verbose "  Easyrsa2 programs successfully moved to: $EASYRSA_SAFE_PKI"
 | 
						|
} #=> up23_move_easyrsa2_programs ()
 | 
						|
 | 
						|
up23_build_v3_vars ()
 | 
						|
{
 | 
						|
	up23_verbose "> Build v3 vars file .."
 | 
						|
 | 
						|
	EASYRSA_EXT="easyrsa-upgrade-23"
 | 
						|
	EASYRSA_VARSV2_TMP="$EASYRSA/vars-v2.tmp.$EASYRSA_EXT"
 | 
						|
	rm -f "$EASYRSA_VARSV2_TMP"
 | 
						|
	EASYRSA_VARSV3_TMP="$EASYRSA/vars-v3.tmp.$EASYRSA_EXT"
 | 
						|
	rm -f "$EASYRSA_VARSV3_TMP"
 | 
						|
	EASYRSA_VARSV3_NEW="$EASYRSA/vars-v3.new.$EASYRSA_EXT"
 | 
						|
	rm -f "$EASYRSA_VARSV3_NEW"
 | 
						|
	EASYRSA_VARSV3_WRN="$EASYRSA/vars-v3.wrn.$EASYRSA_EXT"
 | 
						|
	rm -f "$EASYRSA_VARSV3_WRN"
 | 
						|
 | 
						|
	printf "%s\n" "\
 | 
						|
########################++++++++++#########################
 | 
						|
###                                                     ###
 | 
						|
###  WARNING: THIS FILE WAS AUTOMATICALLY GENERATED     ###
 | 
						|
###           ALL SETTINGS ARE AT THE END OF THE FILE   ###
 | 
						|
###                                                     ###
 | 
						|
########################++++++++++#########################
 | 
						|
 | 
						|
" > "$EASYRSA_VARSV3_WRN" || up23_fail_upgrade "Failed to create $EASYRSA_VARSV3_WRN"
 | 
						|
 | 
						|
	# Create vars v3 temp file from sourced vars v2 key variables
 | 
						|
	{
 | 
						|
		printf "%s\n" "set_var EASYRSA_KEY_SIZE $KEY_SIZE"
 | 
						|
		printf "%s\n" "set_var EASYRSA_REQ_COUNTRY \"$KEY_COUNTRY\""
 | 
						|
		printf "%s\n" "set_var EASYRSA_REQ_PROVINCE \"$KEY_PROVINCE\""
 | 
						|
		printf "%s\n" "set_var EASYRSA_REQ_CITY \"$KEY_CITY\""
 | 
						|
		printf "%s\n" "set_var EASYRSA_REQ_ORG \"$KEY_ORG\""
 | 
						|
		printf "%s\n" "set_var EASYRSA_REQ_EMAIL \"$KEY_EMAIL\""
 | 
						|
		printf "%s\n" "set_var EASYRSA_REQ_OU \"$KEY_OU\""
 | 
						|
		printf "%s\n" 'set_var EASYRSA_NS_SUPPORT "yes"'
 | 
						|
		printf "%s\n" 'set_var EASYRSA_DN "org"'
 | 
						|
		printf "%s\n" 'set_var EASYRSA_RAND_SN "no"'
 | 
						|
		printf "%s\n" ""
 | 
						|
	} > "$EASYRSA_VARSV3_TMP" \
 | 
						|
	|| up23_fail_upgrade "Failed to create $EASYRSA_VARSV3_TMP"
 | 
						|
 | 
						|
	# cat temp files into new v3 vars
 | 
						|
	cat "$EASYRSA_VARSV3_WRN" "$EASYRSA_VARSV3_EXMP" "$EASYRSA_VARSV3_TMP" \
 | 
						|
	> "$EASYRSA_VARSV3_NEW" \
 | 
						|
	|| up23_fail_upgrade "Failed to create $EASYRSA_VARSV3_NEW"
 | 
						|
 | 
						|
	# This file must be created and restored at the end of TEST
 | 
						|
	# for the REAL update to to succeed
 | 
						|
	EASYRSA_VARS_LIVEBKP="$EASYRSA_TARGET_VARSFILE.livebackup"
 | 
						|
	cp "$EASYRSA_VER2_VARSFILE" "$EASYRSA_VARS_LIVEBKP" \
 | 
						|
	|| up23_fail_upgrade "Failed to create $EASYRSA_VARS_LIVEBKP"
 | 
						|
	rm -f "$EASYRSA_VER2_VARSFILE"
 | 
						|
 | 
						|
	# "$EASYRSA_TARGET_VARSFILE" is always $EASYRSA/vars
 | 
						|
	cp "$EASYRSA_VARSV3_NEW" "$EASYRSA_TARGET_VARSFILE" \
 | 
						|
	|| up23_fail_upgrade "copy $EASYRSA_VARSV3_NEW to $EASYRSA_TARGET_VARSFILE"
 | 
						|
 | 
						|
	# Delete temp files
 | 
						|
	rm -f "$EASYRSA_VARSV2_TMP" "$EASYRSA_VARSV3_TMP" \
 | 
						|
	"$EASYRSA_VARSV3_NEW" "$EASYRSA_VARSV3_WRN"
 | 
						|
 | 
						|
	up23_verbose "> OK"
 | 
						|
	up23_verbose "  New v3 vars file created in: $EASYRSA_TARGET_VARSFILE"
 | 
						|
} #=> up23_build_v3_vars ()
 | 
						|
 | 
						|
up23_do_upgrade_23 ()
 | 
						|
{
 | 
						|
	up23_verbose "============================================================================"
 | 
						|
	up23_verbose "Begin ** $1 ** upgrade process .."
 | 
						|
	up23_verbose ""
 | 
						|
	up23_verbose "Easyrsa upgrade version: $EASYRSA_UPGRADE_23"
 | 
						|
	up23_verbose ""
 | 
						|
 | 
						|
	up23_verify_new_pki
 | 
						|
	up23_verify_current_pki
 | 
						|
	up23_verify_current_ca
 | 
						|
	up23_backup_current_pki
 | 
						|
	up23_create_new_pki
 | 
						|
	up23_upgrade_ca
 | 
						|
	up23_move_easyrsa2_programs
 | 
						|
	up23_build_v3_vars
 | 
						|
	up23_create_openssl_cnf
 | 
						|
 | 
						|
	if [ "$NOSAVE" -eq 0 ]
 | 
						|
	then
 | 
						|
		# Must stay in this order
 | 
						|
		# New created dirs: EASYRSA_NEW_PKI and EASYRSA_SAFE_PKI
 | 
						|
		rm -rf "$EASYRSA_NEW_PKI"
 | 
						|
		rm -rf "$EASYRSA_SAFE_PKI"
 | 
						|
		# EASYRSA_TARGET_VARSFILE is always the new created v3 vars
 | 
						|
		# Need to know if this fails
 | 
						|
		rm "$EASYRSA_TARGET_VARSFILE" \
 | 
						|
		|| up23_fail_upgrade "remove new vars file: $EASYRSA_TARGET_VARSFILE"
 | 
						|
		# EASYRSA_VER2_VARSFILE is either v2 *nix ./vars or Win vars.bat
 | 
						|
		# Need this dance because v2 vars is same name as v3 vars above
 | 
						|
		cp "$EASYRSA_VARS_LIVEBKP" "$EASYRSA_VER2_VARSFILE"
 | 
						|
	fi
 | 
						|
	rm -f "$EASYRSA_VARS_LIVEBKP"
 | 
						|
} #= up23_do_upgrade_23 ()
 | 
						|
 | 
						|
up23_manage_upgrade_23 ()
 | 
						|
{
 | 
						|
	EASYRSA_UPGRADE_VERSION="v1.0a (2020/01/08)"
 | 
						|
	EASYRSA_UPGRADE_TYPE="$1"
 | 
						|
	EASYRSA_FOUND_VARS=0
 | 
						|
 | 
						|
	# Verify all existing versions of vars/vars.bat
 | 
						|
	if [ -f "$vars" ]
 | 
						|
	then
 | 
						|
		if grep -q 'Complain if a user tries to do this:' "$vars"
 | 
						|
		then
 | 
						|
			EASYRSA_FOUND_VARS=1
 | 
						|
			EASYRSA_VARS_IS_VER3=1
 | 
						|
		fi
 | 
						|
 | 
						|
		# Easyrsa v3 does not use NOR allow use of `export`.
 | 
						|
		if grep -q 'export' "$vars"
 | 
						|
		then
 | 
						|
			EASYRSA_FOUND_VARS=1
 | 
						|
			EASYRSA_VARS_IS_VER2=1
 | 
						|
			EASYRSA_VER2_VARSFILE="$vars"
 | 
						|
			EASYRSA_TARGET_VARSFILE="$vars"
 | 
						|
		fi
 | 
						|
	fi
 | 
						|
 | 
						|
	if [ -f "$EASYRSA/vars.bat" ]
 | 
						|
	then
 | 
						|
		EASYRSA_FOUND_VARS=1
 | 
						|
		EASYRSA_VARS_IS_WIN2=1
 | 
						|
		EASYRSA_VER2_VARSFILE="$EASYRSA/vars.bat"
 | 
						|
		EASYRSA_TARGET_VARSFILE="$EASYRSA/vars"
 | 
						|
	fi
 | 
						|
 | 
						|
	if [ $EASYRSA_FOUND_VARS -ne 1 ];
 | 
						|
	then
 | 
						|
		die echo "vars file not found"
 | 
						|
	fi
 | 
						|
 | 
						|
	# Only allow specific vars/vars.bat to exist
 | 
						|
	if [ "$EASYRSA_VARS_IS_VER3" ] && [ "$EASYRSA_VARS_IS_VER2" ]
 | 
						|
	then
 | 
						|
		die "Verify your current vars file, v3 cannot use 'export'."
 | 
						|
	fi
 | 
						|
 | 
						|
	if [ "$EASYRSA_VARS_IS_VER3" ] && [ "$EASYRSA_VARS_IS_WIN2" ]
 | 
						|
	then
 | 
						|
		die "Verify your current vars/vars.bat file, cannot have both."
 | 
						|
	fi
 | 
						|
 | 
						|
	if [ "$EASYRSA_VARS_IS_VER2" ] && [ "$EASYRSA_VARS_IS_WIN2" ]
 | 
						|
	then
 | 
						|
		die "Verify your current vars/vars.bat file, cannot have both."
 | 
						|
	fi
 | 
						|
 | 
						|
	# Die on invalid upgrade type or environment
 | 
						|
	if [ "$EASYRSA_UPGRADE_TYPE" = "ca" ]
 | 
						|
	then
 | 
						|
		if [ "$EASYRSA_VARS_IS_VER3" ]
 | 
						|
		then
 | 
						|
			# v3 ensure index.txt.attr "unique_subject = no"
 | 
						|
			up23_upgrade_ca
 | 
						|
			unset EASYRSA_BATCH
 | 
						|
			notice "Your CA is fully up to date."
 | 
						|
			return 0
 | 
						|
		else
 | 
						|
			die "Only v3 PKI CA can be upgraded."
 | 
						|
		fi
 | 
						|
	fi
 | 
						|
 | 
						|
	if [ "$EASYRSA_UPGRADE_TYPE" = "pki" ]
 | 
						|
	then
 | 
						|
		if [ "$EASYRSA_VARS_IS_VER3" ]
 | 
						|
		then
 | 
						|
			unset EASYRSA_BATCH
 | 
						|
			notice "Your PKI is fully up to date."
 | 
						|
			return 0
 | 
						|
		fi
 | 
						|
	else
 | 
						|
		die "upgrade type must be 'pki' or 'ca'."
 | 
						|
	fi
 | 
						|
 | 
						|
	# PKI is potentially suitable for upgrade
 | 
						|
 | 
						|
	warn "
 | 
						|
=========================================================================
 | 
						|
 | 
						|
                           * WARNING *
 | 
						|
 | 
						|
Found settings from EasyRSA-v2 which are not compatible with EasyRSA-v3.
 | 
						|
Before you can continue, EasyRSA must upgrade your settings and PKI.
 | 
						|
* Found EASYRSA and vars file:
 | 
						|
  $EASYRSA
 | 
						|
  $EASYRSA_VER2_VARSFILE :
 | 
						|
 | 
						|
Further info:
 | 
						|
* https://community.openvpn.net/openvpn/wiki/easyrsa-upgrade
 | 
						|
 | 
						|
Easyrsa upgrade version: $EASYRSA_UPGRADE_VERSION
 | 
						|
=========================================================================
 | 
						|
"
 | 
						|
 | 
						|
# Test upgrade
 | 
						|
 | 
						|
	NOSAVE=0
 | 
						|
 | 
						|
	confirm "* EasyRSA **TEST** upgrade (Changes will NOT be written): " "yes" "
 | 
						|
This upgrade will TEST that the upgrade works BEFORE making any changes."
 | 
						|
 | 
						|
	up23_do_upgrade_23 "TEST"
 | 
						|
 | 
						|
	notice "
 | 
						|
=========================================================================
 | 
						|
 | 
						|
                             * NOTICE *
 | 
						|
 | 
						|
EasyRSA upgrade **TEST** has successfully completed.
 | 
						|
"
 | 
						|
# Upgrade for REAL
 | 
						|
 | 
						|
	NOSAVE=1
 | 
						|
 | 
						|
	confirm "* EasyRSA **REAL** upgrade (Changes WILL be written): " "yes" "
 | 
						|
=========================================================================
 | 
						|
 | 
						|
                             * WARNING *
 | 
						|
 | 
						|
Run REAL upgrade: Answer yes (Once completed you will have a version 3 PKI)
 | 
						|
Terminate upgrade: Answer no (No changes have been made to your current PKI)
 | 
						|
"
 | 
						|
 | 
						|
	confirm "* Confirm **REAL** upgrade (Changes will be written): " "yes" "
 | 
						|
=========================================================================
 | 
						|
 | 
						|
                          * SECOND WARNING *
 | 
						|
 | 
						|
This upgrade will permanently write changes to your PKI !
 | 
						|
(With full backup backout)
 | 
						|
"
 | 
						|
	up23_do_upgrade_23 "REAL"
 | 
						|
 | 
						|
	notice "
 | 
						|
=========================================================================
 | 
						|
 | 
						|
                             * NOTICE *
 | 
						|
 | 
						|
Your settings and PKI have been successfully upgraded to EasyRSA version3
 | 
						|
 | 
						|
A backup of your current PKI is here:
 | 
						|
  $EASYRSA_SAFE_PKI
 | 
						|
 | 
						|
                        * IMPORTANT NOTICE *
 | 
						|
 | 
						|
1. YOU MUST VERIFY THAT YOUR NEW ./vars FILE IS SETUP CORRECTLY
 | 
						|
2. IF YOU ARE USING WINDOWS YOU MUST ENSURE THAT openssl IS CORRECTLY DEFINED
 | 
						|
   IN ./vars (example follows)
 | 
						|
 | 
						|
 #
 | 
						|
 # This sample is in Windows syntax -- edit it for your path if not using PATH:
 | 
						|
 # set_var EASYRSA_OPENSSL   \"C:/Program Files/OpenSSL-Win32/bin/openssl.exe\"
 | 
						|
 #
 | 
						|
 # Alternate location (Note: Forward slash '/' is correct for Windpws):
 | 
						|
 # set_var EASYRSA_OPENSSL   \"C:/Program Files/Openvpn/bin/openssl.exe\"
 | 
						|
 #
 | 
						|
 | 
						|
3. Finally, you can verify that easyrsa works by using these two commands:
 | 
						|
    ./easyrsa show-ca (Verify that your CA is intact and correct)
 | 
						|
    ./easyrsa gen-crl ((re)-generate a CRL file)
 | 
						|
 | 
						|
Further info:
 | 
						|
* https://community.openvpn.net/openvpn/wiki/easyrsa-upgrade"
 | 
						|
          up23_verbose "
 | 
						|
                   * UPGRADE COMPLETED SUCCESSFULLY *
 | 
						|
"
 | 
						|
 | 
						|
return 0
 | 
						|
 | 
						|
} # => up23_manage_upgrade_23 ()
 | 
						|
 | 
						|
print_version()
 | 
						|
{
 | 
						|
		cat <<HERE
 | 
						|
EasyRSA Version Information
 | 
						|
Version:     3.0.8
 | 
						|
Generated:   Wed Sep  9 15:59:45 CDT 2020
 | 
						|
SSL Lib:     $(openssl version)
 | 
						|
Git Commit:  f12e00e53b4f486ce3d119ca429198780fa694ac
 | 
						|
Source Repo: https://github.com/OpenVPN/easy-rsa
 | 
						|
HERE
 | 
						|
		exit 0
 | 
						|
} # => print_version ()
 | 
						|
 | 
						|
 | 
						|
########################################
 | 
						|
# Invocation entry point:
 | 
						|
 | 
						|
NL='
 | 
						|
'
 | 
						|
 | 
						|
# Be secure with a restrictive umask
 | 
						|
[ -z "$EASYRSA_NO_UMASK" ] && umask 077
 | 
						|
 | 
						|
# Parse options
 | 
						|
while :; do
 | 
						|
	# Separate option from value:
 | 
						|
	opt="${1%%=*}"
 | 
						|
	val="${1#*=}"
 | 
						|
	empty_ok="" # Empty values are not allowed unless excepted
 | 
						|
 | 
						|
	case "$opt" in
 | 
						|
	--days)
 | 
						|
		export EASYRSA_CERT_EXPIRE="$val"
 | 
						|
		export EASYRSA_CA_EXPIRE="$val"
 | 
						|
		export EASYRSA_CRL_DAYS="$val"
 | 
						|
		;;
 | 
						|
	--pki-dir)
 | 
						|
		export EASYRSA_PKI="$val" ;;
 | 
						|
	--use-algo)
 | 
						|
		export EASYRSA_ALGO="$val" ;;
 | 
						|
	--keysize)
 | 
						|
		export EASYRSA_KEY_SIZE="$val" ;;
 | 
						|
	--curve)
 | 
						|
		export EASYRSA_CURVE="$val" ;;
 | 
						|
	--dn-mode)
 | 
						|
		export EASYRSA_DN="$val" ;;
 | 
						|
	--req-cn)
 | 
						|
		export EASYRSA_REQ_CN="$val" ;;
 | 
						|
	--digest)
 | 
						|
		export EASYRSA_DIGEST="$val" ;;
 | 
						|
	--req-c)
 | 
						|
		empty_ok=1
 | 
						|
		export EASYRSA_REQ_COUNTRY="$val" ;;
 | 
						|
	--req-st)
 | 
						|
		empty_ok=1
 | 
						|
		export EASYRSA_REQ_PROVINCE="$val" ;;
 | 
						|
	--req-city)
 | 
						|
		empty_ok=1
 | 
						|
		export EASYRSA_REQ_CITY="$val" ;;
 | 
						|
	--req-org)
 | 
						|
		empty_ok=1
 | 
						|
		export EASYRSA_REQ_ORG="$val" ;;
 | 
						|
	--req-email)
 | 
						|
		empty_ok=1
 | 
						|
		export EASYRSA_REQ_EMAIL="$val" ;;
 | 
						|
	--req-ou)
 | 
						|
		empty_ok=1
 | 
						|
		export EASYRSA_REQ_OU="$val" ;;
 | 
						|
	--ns-cert)
 | 
						|
		export EASYRSA_NS_SUPPORT="$val" ;;
 | 
						|
	--ns-comment)
 | 
						|
		empty_ok=1
 | 
						|
		export EASYRSA_NS_COMMENT="$val" ;;
 | 
						|
	--batch)
 | 
						|
		empty_ok=1
 | 
						|
		export EASYRSA_BATCH=1 ;;
 | 
						|
	--passin)
 | 
						|
		export EASYRSA_PASSIN="$val";;
 | 
						|
	--passout)
 | 
						|
		export EASYRSA_PASSOUT="$val";;
 | 
						|
	--subca-len)
 | 
						|
		export EASYRSA_SUBCA_LEN="$val" ;;
 | 
						|
	--vars)
 | 
						|
		export EASYRSA_VARS_FILE="$val" ;;
 | 
						|
	--copy-ext)
 | 
						|
		empty_ok=1
 | 
						|
		export EASYRSA_CP_EXT=1 ;;
 | 
						|
	--subject-alt-name)
 | 
						|
		export EASYRSA_EXTRA_EXTS="\
 | 
						|
$EASYRSA_EXTRA_EXTS
 | 
						|
subjectAltName = $val" ;;
 | 
						|
	--version)
 | 
						|
		print_version
 | 
						|
		;;
 | 
						|
	*)
 | 
						|
		break ;;
 | 
						|
	esac
 | 
						|
 | 
						|
	# fatal error when no value was provided
 | 
						|
	if [ ! $empty_ok ] && { [ "$val" = "$1" ] || [ -z "$val" ]; }; then
 | 
						|
		die "Missing value to option: $opt"
 | 
						|
	fi
 | 
						|
 | 
						|
	shift
 | 
						|
done
 | 
						|
 | 
						|
# Intelligent env-var detection and auto-loading:
 | 
						|
vars_setup
 | 
						|
 | 
						|
# Register cleanup on EXIT
 | 
						|
trap "cleanup" EXIT
 | 
						|
# When SIGHUP, SIGINT, SIGQUIT, SIGABRT and SIGTERM,
 | 
						|
# explicitly exit to signal EXIT (non-bash shells)
 | 
						|
trap "exit 1" 1
 | 
						|
trap "exit 2" 2
 | 
						|
trap "exit 3" 3
 | 
						|
trap "exit 6" 6
 | 
						|
trap "exit 14" 15
 | 
						|
 | 
						|
# Upgrade: EasyRSA v2.x to EasyRSA v3.x
 | 
						|
# Upgrade: EasyRSA < v3.0.6 to v3.0.6+
 | 
						|
#up23_manage_upgrade_23
 | 
						|
 | 
						|
# determine how we were called, then hand off to the function responsible
 | 
						|
cmd="$1"
 | 
						|
[ -n "$1" ] && shift # scrape off command
 | 
						|
case "$cmd" in
 | 
						|
	init-pki|clean-all)
 | 
						|
		init_pki "$@"
 | 
						|
		;;
 | 
						|
	build-ca)
 | 
						|
		build_ca "$@"
 | 
						|
		;;
 | 
						|
	gen-dh)
 | 
						|
		gen_dh
 | 
						|
		;;
 | 
						|
	gen-req)
 | 
						|
		gen_req "$@"
 | 
						|
		;;
 | 
						|
	sign|sign-req)
 | 
						|
		sign_req "$@"
 | 
						|
		;;
 | 
						|
	build-client-full)
 | 
						|
		build_full client "$@"
 | 
						|
		;;
 | 
						|
	build-server-full)
 | 
						|
		build_full server "$@"
 | 
						|
		;;
 | 
						|
	build-serverClient-full)
 | 
						|
		build_full serverClient "$@"
 | 
						|
		;;
 | 
						|
	gen-crl)
 | 
						|
		gen_crl
 | 
						|
		;;
 | 
						|
	revoke)
 | 
						|
		revoke "$@"
 | 
						|
		;;
 | 
						|
	renew)
 | 
						|
		renew "$@"
 | 
						|
		;;
 | 
						|
	import-req)
 | 
						|
		import_req "$@"
 | 
						|
		;;
 | 
						|
	export-p12)
 | 
						|
		export_pkcs p12 "$@"
 | 
						|
		;;
 | 
						|
	export-p7)
 | 
						|
		export_pkcs p7 "$@"
 | 
						|
		;;
 | 
						|
	export-p8)
 | 
						|
		export_pkcs p8 "$@"
 | 
						|
		;;
 | 
						|
	set-rsa-pass)
 | 
						|
		set_pass rsa "$@"
 | 
						|
		;;
 | 
						|
	set-ec-pass)
 | 
						|
		set_pass ec "$@"
 | 
						|
		;;
 | 
						|
	update-db)
 | 
						|
		update_db
 | 
						|
		;;
 | 
						|
	show-req)
 | 
						|
		show req "$@"
 | 
						|
		;;
 | 
						|
	show-cert)
 | 
						|
		show cert "$@"
 | 
						|
		;;
 | 
						|
	show-ca)
 | 
						|
		show_ca "$@"
 | 
						|
		;;
 | 
						|
	upgrade)
 | 
						|
		up23_manage_upgrade_23 "$@"
 | 
						|
		;;
 | 
						|
	""|help|-h|--help|--usage)
 | 
						|
		cmd_help "$1"
 | 
						|
		exit 0
 | 
						|
		;;
 | 
						|
	version)
 | 
						|
		print_version
 | 
						|
		;;
 | 
						|
	*)
 | 
						|
		die "Unknown command '$cmd'. Run without commands for usage help."
 | 
						|
		;;
 | 
						|
esac
 | 
						|
 | 
						|
# vim: ft=sh nu ai sw=8 ts=8 noet
 |