Subversion Repositories configs

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
192 - 1
#!/bin/sh
2
 
3
# Easy-RSA 3 -- A Shell-based CA Utility
4
#
5
# Copyright (C) 2018 by the Open-Source OpenVPN development community.
6
# A full list of contributors can be found in the ChangeLog.
7
#
8
# This code released under version 2 of the GNU GPL; see COPYING and the
9
# Licensing/ directory of this project for full licensing details.
10
 
11
# Help/usage output to stdout
12
usage() {
13
	# command help:
14
	print "
15
Easy-RSA 3 usage and overview
16
 
17
USAGE: easyrsa [options] COMMAND [command-options]
18
 
19
A list of commands is shown below. To get detailed usage and help for a
20
command, run:
21
  ./easyrsa help COMMAND
22
 
23
For a listing of options that can be supplied before the command, use:
24
  ./easyrsa help options
25
 
26
Here is the list of commands available with a short syntax reminder. Use the
27
'help' command above to get full usage details.
28
 
29
  init-pki
30
  build-ca [ cmd-opts ]
31
  gen-dh
32
  gen-req <filename_base> [ cmd-opts ]
33
  sign-req <type> <filename_base>
34
  build-client-full <filename_base> [ cmd-opts ]
35
  build-server-full <filename_base> [ cmd-opts ]
36
  revoke <filename_base> [cmd-opts]
37
  renew <filename_base> [cmd-opts]
38
  build-serverClient-full <filename_base> [ cmd-opts ]
39
  gen-crl
40
  update-db
41
  show-req <filename_base> [ cmd-opts ]
42
  show-cert <filename_base> [ cmd-opts ]
43
  show-ca [ cmd-opts ]
44
  import-req <request_file_path> <short_basename>
45
  export-p7 <filename_base> [ cmd-opts ]
46
  export-p12 <filename_base> [ cmd-opts ]
47
  set-rsa-pass <filename_base> [ cmd-opts ]
48
  set-ec-pass <filename_base> [ cmd-opts ]
49
  upgrade <type>
50
"
51
 
52
	# collect/show dir status:
53
	err_source="Not defined: vars autodetect failed and no value provided"
54
	work_dir="${EASYRSA:-$err_source}"
55
	pki_dir="${EASYRSA_PKI:-$err_source}"
56
	print "\
57
DIRECTORY STATUS (commands would take effect on these locations)
58
  EASYRSA: $work_dir
59
      PKI: $pki_dir
60
"
61
} # => usage()
62
 
63
# Detailed command help
64
# When called with no args, calls usage(), otherwise shows help for a command
65
cmd_help() {
66
	text=""
67
	opts=""
68
	case "$1" in
69
		init-pki|clean-all) text="
70
  init-pki [ cmd-opts ]
71
      Removes & re-initializes the PKI dir for a clean PKI" ;;
72
		build-ca) text="
73
  build-ca [ cmd-opts ]
74
      Creates a new CA"
75
      			opts="
76
        nopass  - do not encrypt the CA key (default is encrypted)
77
        subca   - create an intermediate CA keypair and request (default is a root CA)
78
        intca   - alias to the above" ;;
79
		gen-dh) text="
80
  gen-dh
81
      Generates DH (Diffie-Hellman) parameters" ;;
82
		gen-req) text="
83
  gen-req <filename_base> [ cmd-opts ]
84
      Generate a standalone keypair and request (CSR)
85
 
86
      This request is suitable for sending to a remote CA for signing."
87
      			opts="
88
        nopass  - do not encrypt the private key (default is encrypted)" ;;
89
		sign|sign-req) text="
90
  sign-req <type> <filename_base>
91
      Sign a certificate request of the defined type. <type> must be a known
92
      type such as 'client', 'server', 'serverClient', or 'ca' (or a user-added type.)
93
 
94
      This request file must exist in the reqs/ dir and have a .req file
95
      extension. See import-req below for importing reqs from other sources." ;;
96
		build|build-client-full|build-server-full|build-serverClient-full) text="
97
  build-client-full <filename_base> [ cmd-opts ]
98
  build-server-full <filename_base> [ cmd-opts ]
99
  build-serverClient-full <filename_base> [ cmd-opts ]
100
      Generate a keypair and sign locally for a client and/or server
101
 
102
      This mode uses the <filename_base> as the X509 CN."
103
			opts="
104
        nopass  - do not encrypt the private key (default is encrypted)
105
        inline  - create an inline credentials file for this node" ;;
106
		revoke) text="
107
  revoke <filename_base> [reason]
108
      Revoke a certificate specified by the filename_base, with an optional
109
      revocation reason that is one of:
110
        unspecified
111
        keyCompromise
112
        CACompromise
113
        affiliationChanged
114
        superseded
115
        cessationOfOperation
116
        certificateHold";;
117
		renew) text="
118
  renew <filename_base> [ cmd-opts ]
119
      Renew a certificate specified by the filename_base"
120
				opts="
121
        nopass  - do not encrypt the private key (default is encrypted)" ;;
122
		gen-crl) text="
123
  gen-crl
124
      Generate a CRL" ;;
125
		update-db) text="
126
  update-db
127
      Update the index.txt database
128
 
129
      This command will use the system time to update the status of issued
130
      certificates." ;;
131
      		show-req|show-cert) text="
132
  show-req  <filename_base> [ cmd-opts ]
133
  show-cert <filename_base> [ cmd-opts ]
134
      Shows details of the req or cert referenced by filename_base
135
 
136
      Human-readable output is shown, including any requested cert options when
137
      showing a request."
138
      			opts="
139
          full   - show full req/cert info, including pubkey/sig data" ;;
140
		show-ca) text="
141
  show-ca [ cmd-opts ]
142
      Shows details of the CA cert
143
 
144
      Human-readable output is shown."
145
			opts="
146
          full   - show full cert info, including pubkey/sig data" ;;
147
		import-req) text="
148
  import-req <request_file_path> <short_basename>
149
      Import a certificate request from a file
150
 
151
      This will copy the specified file into the reqs/ dir in
152
      preparation for signing.
153
      The <short_basename> is the filename base to create.
154
 
155
      Example usage:
156
        import-req /some/where/bob_request.req bob" ;;
157
		export-p12) text="
158
  export-p12 <filename_base> [ cmd-opts ]
159
      Export a PKCS#12 file with the keypair specified by <filename_base>"
160
			opts="
161
        noca  - do not include the ca.crt file in the PKCS12 output
162
        nokey - do not include the private key in the PKCS12 output" ;;
163
		export-p7) text="
164
  export-p7 <filename_base> [ cmd-opts ]
165
      Export a PKCS#7 file with the pubkey specified by <filename_base>"
166
			opts="
167
        noca  - do not include the ca.crt file in the PKCS7 output" ;;
168
		set-rsa-pass|set-ec-pass) text="
169
  set-rsa-pass <filename_base> [ cmd-opts ]
170
  set-ec-pass <filename_base> [ cmd-opts ]
171
      Set a new passphrase on an RSA or EC key for the listed <filename_base>."
172
                        opts="
173
        nopass - use no password and leave the key unencrypted
174
        file   - (advanced) treat the file as a raw path, not a short-name" ;;
175
		upgrade) text="
176
  upgrade <type>
177
      Upgrade EasyRSA PKI and/or CA. <type> must be one of:
178
        pki - Upgrade EasyRSA v2.x PKI to EasyRSA v3.x PKI (includes CA below)
179
        ca  - Upgrade EasyRSA v3.0.5 CA or older to EasyRSA v3.0.6 CA or later." ;;
180
		altname|subjectaltname|san) text="
181
  --subject-alt-name=SAN_FORMAT_STRING
182
      This global option adds a subjectAltName to the request or issued
183
      certificate. It MUST be in a valid format accepted by openssl or
184
      req/cert generation will fail. Note that including multiple such names
185
      requires them to be comma-separated; further invocations of this
186
      option will REPLACE the value.
187
 
188
      Examples of the SAN_FORMAT_STRING shown below:
189
        DNS:alternate.example.net
190
        DNS:primary.example.net,DNS:alternate.example.net
191
        IP:203.0.113.29
192
        email:alternate@example.net" ;;
193
		options)
194
			opt_usage ;;
195
		"")
196
			usage ;;
197
		*) text="
198
  Unknown command: '$1' (try without commands for a list of commands)" ;;
199
	esac
200
 
201
	# display the help text
202
	print "$text"
203
	[ -n "$opts" ] && print "
204
      cmd-opts is an optional set of command options from this list:
205
$opts"
206
} # => cmd_help()
207
 
208
# Options usage
209
opt_usage() {
210
	print "
211
Easy-RSA Global Option Flags
212
 
213
The following options may be provided before the command. Options specified
214
at runtime override env-vars and any 'vars' file in use. Unless noted,
215
non-empty values to options are mandatory.
216
 
217
General options:
218
 
219
--batch         : set automatic (no-prompts when possible) mode
220
--passin=ARG    : set -passin ARG for openssl
221
--passout=ARG   : set -passout ARG for openssl
222
--pki-dir=DIR   : declares the PKI directory
223
--vars=FILE     : define a specific 'vars' file to use for Easy-RSA config
224
 
225
Certificate & Request options: (these impact cert/req field values)
226
 
227
--days=#        : sets the signing validity to the specified number of days
228
--digest=ALG    : digest to use in the requests & certificates
229
--dn-mode=MODE  : DN mode to use (cn_only or org)
230
--keysize=#     : size in bits of keypair to generate
231
--req-cn=NAME   : default CN to use
232
--subca-len=#   : path length of signed intermediate CA certs; must be >= 0 if used
233
--subject-alt-name : Add a subjectAltName. For more info and syntax, see:
234
                     ./easyrsa help altname
235
--use-algo=ALG  : crypto alg to use: choose rsa (default) or ec
236
--curve=NAME    : for elliptic curve, sets the named curve to use
237
--copy-ext      : Copy included request X509 extensions (namely subjAltName
238
 
239
Organizational DN options: (only used with the 'org' DN mode)
240
  (values may be blank for org DN options)
241
 
242
--req-c=CC        : country code (2-letters)
243
--req-st=NAME     : State/Province
244
--req-city=NAME   : City/Locality
245
--req-org=NAME    : Organization
246
--req-email=NAME  : Email addresses
247
--req-ou=NAME     : Organizational Unit
248
 
249
Deprecated features:
250
 
251
--ns-cert=YESNO       : yes or no to including deprecated NS extensions
252
--ns-comment=COMMENT  : NS comment to include (value may be blank)
253
"
254
} # => opt_usage()
255
 
256
# Wrapper around printf - clobber print since it's not POSIX anyway
257
# shellcheck disable=SC1117
258
print() { printf "%s\n" "$*"; }
259
 
260
# Exit fatally with a message to stderr
261
# present even with EASYRSA_BATCH as these are fatal problems
262
die() {
263
	print "
264
Easy-RSA error:
265
 
266
$1" 1>&2
267
	exit "${2:-1}"
268
} # => die()
269
 
270
# non-fatal warning output
271
warn() {
272
	[ ! "$EASYRSA_BATCH" ] && \
273
		print "
274
$1" 1>&2
275
} # => warn()
276
 
277
# informational notices to stdout
278
notice() {
279
	[ ! "$EASYRSA_BATCH" ] && \
280
		print "
281
$1"
282
} # => notice()
283
 
284
# yes/no case-insensitive match (operates on stdin pipe)
285
# Returns 0 when input contains yes, 1 for no, 2 for no match
286
# If both strings are present, returns 1; first matching line returns.
287
awk_yesno() {
288
	#shellcheck disable=SC2016
289
	awkscript='
290
BEGIN {IGNORECASE=1; r=2}
291
{       if(match($0,"no")) {r=1; exit}
292
        if(match($0,"yes")) {r=0; exit}
293
} END {exit r}'
294
	awk "$awkscript"
295
} # => awk_yesno()
296
 
297
# intent confirmation helper func
298
# returns without prompting in EASYRSA_BATCH
299
confirm() {
300
	[ "$EASYRSA_BATCH" ] && return
301
	prompt="$1"
302
	value="$2"
303
	msg="$3"
304
	input=""
305
	print "
306
$msg
307
 
308
Type the word '$value' to continue, or any other input to abort."
309
	printf %s "  $prompt"
310
	#shellcheck disable=SC2162
311
	read input
312
	[ "$input" = "$value" ] && return
313
	notice "Aborting without confirmation."
314
	exit 9
315
} # => confirm()
316
 
317
# mktemp wrapper
318
easyrsa_mktemp() {
319
	[ -n "$EASYRSA_TEMP_DIR_session" ] || die "EASYRSA_TEMP_DIR_session not initialized!"
320
	[ -d "$EASYRSA_TEMP_DIR_session" ] || mkdir -p "$EASYRSA_TEMP_DIR_session" ||
321
	       die "Could not create temporary directory '$EASYRSA_TEMP_DIR_session'. Permission or concurrency problem?"
322
	[ -d "$EASYRSA_TEMP_DIR_session" ] || die "Temporary directory '$EASYRSA_TEMP_DIR_session' does not exist"
323
 
324
	template="$EASYRSA_TEMP_DIR_session/tmp.XXXXXX"
325
	tempfile=$(mktemp "$template") || return
326
 
327
	# win32 mktemp shipped by easyrsa returns template as file!
328
	if [ "$template" = "$tempfile" ]; then
329
		# but win32 mktemp -d does work
330
		# but win32 mktemp -u does not work
331
		tempfile=$(mktemp -du "$tempfile") || return
332
		printf "" > "$tempfile" || return
333
	fi
334
	echo "$tempfile"
335
} # => easyrsa_mktemp
336
 
337
# remove temp files and do terminal cleanups
338
cleanup() {
339
	[ -z "$EASYRSA_TEMP_DIR_session" ] || rm -rf "$EASYRSA_TEMP_DIR_session"
340
	# shellcheck disable=SC2039
341
	(stty echo 2>/dev/null) || { (set -o echo 2>/dev/null) && set -o echo; }
342
	echo "" # just to get a clean line
343
} # => cleanup()
344
 
345
easyrsa_openssl() {
346
	openssl_command=$1; shift
347
 
348
	case $openssl_command in
349
		makesafeconf) has_config=true;;
350
		ca|req|srp|ts) has_config=true;;
351
		*) has_config=false;;
352
	esac
353
 
354
	if ! $has_config; then
355
		"$EASYRSA_OPENSSL" "$openssl_command" "$@"
356
		return
357
	fi
358
 
359
	easyrsa_openssl_conf=$(easyrsa_mktemp) || die "Failed to create temporary file"
360
	easyrsa_extra_exts=
361
	if [ -n "$EASYRSA_EXTRA_EXTS" ]; then
362
		easyrsa_extra_exts=$(easyrsa_mktemp) || die "Failed to create temporary file"
363
		cat >"$easyrsa_extra_exts" <<-EOF
364
			req_extensions = req_extra
365
			[ req_extra ]
366
			$EASYRSA_EXTRA_EXTS
367
		EOF
368
	fi
369
 
370
	# Make LibreSSL safe config file from OpenSSL config file
371
	sed \
372
		-e "s\`ENV::EASYRSA\`EASYRSA\`g" \
373
		-e "s\`\$dir\`$EASYRSA_PKI\`g" \
374
		-e "s\`\$EASYRSA_PKI\`$EASYRSA_PKI\`g" \
375
		-e "s\`\$EASYRSA_CERT_EXPIRE\`$EASYRSA_CERT_EXPIRE\`g" \
376
		-e "s\`\$EASYRSA_CRL_DAYS\`$EASYRSA_CRL_DAYS\`g" \
377
		-e "s\`\$EASYRSA_DIGEST\`$EASYRSA_DIGEST\`g" \
378
		-e "s\`\$EASYRSA_KEY_SIZE\`$EASYRSA_KEY_SIZE\`g" \
379
		-e "s\`\$EASYRSA_DIGEST\`$EASYRSA_DIGEST\`g" \
380
		-e "s\`\$EASYRSA_DN\`$EASYRSA_DN\`g" \
381
		-e "s\`\$EASYRSA_REQ_COUNTRY\`$EASYRSA_REQ_COUNTRY\`g" \
382
		-e "s\`\$EASYRSA_REQ_PROVINCE\`$EASYRSA_REQ_PROVINCE\`g" \
383
		-e "s\`\$EASYRSA_REQ_CITY\`$EASYRSA_REQ_CITY\`g" \
384
		-e "s\`\$EASYRSA_REQ_ORG\`$EASYRSA_REQ_ORG\`g" \
385
		-e "s\`\$EASYRSA_REQ_OU\`$EASYRSA_REQ_OU\`g" \
386
		-e "s\`\$EASYRSA_REQ_CN\`$EASYRSA_REQ_CN\`g" \
387
		-e "s\`\$EASYRSA_REQ_EMAIL\`$EASYRSA_REQ_EMAIL\`g" \
388
		${EASYRSA_EXTRA_EXTS:+-e "/^#%EXTRA_EXTS%/r $easyrsa_extra_exts"} \
389
		"$EASYRSA_SSL_CONF" > "$easyrsa_openssl_conf" ||
390
		die "Failed to update $easyrsa_openssl_conf"
391
 
392
	if [ "$openssl_command" = "makesafeconf" ]; then
393
		cp "$easyrsa_openssl_conf" "$EASYRSA_SAFE_CONF"
394
		err=$?
395
	else
396
		"$EASYRSA_OPENSSL" "$openssl_command" -config "$easyrsa_openssl_conf" "$@"
397
		err=$?
398
	fi
399
 
400
	rm -f "$easyrsa_openssl_conf"
401
	rm -f "$easyrsa_extra_exts"
402
	return $err
403
} # => easyrsa_openssl
404
 
405
vars_source_check() {
406
	# Check for defined EASYRSA_PKI
407
	[ -n "$EASYRSA_PKI" ] || die "\
408
EASYRSA_PKI env-var undefined"
409
} # => vars_source_check()
410
 
411
# Verify supplied curve exists and generate curve file if needed
412
verify_curve_ec() {
413
	if ! "$EASYRSA_OPENSSL" ecparam -name "$EASYRSA_CURVE" > /dev/null; then
414
		die "\
415
Curve $EASYRSA_CURVE not found. Run openssl ecparam -list_curves to show a
416
list of supported curves."
417
	fi
418
 
419
	# Check that the ecparams dir exists
420
	[ -d "$EASYRSA_EC_DIR" ] || mkdir "$EASYRSA_EC_DIR" || die "\
421
Failed creating ecparams dir (permissions?) at:
422
$EASYRSA_EC_DIR"
423
 
424
	# Check that the required ecparams file exists
425
	out="$EASYRSA_EC_DIR/${EASYRSA_CURVE}.pem"
426
	[ -f "$out" ] && return 0
427
	"$EASYRSA_OPENSSL" ecparam -name "$EASYRSA_CURVE" -out "$out" || die "\
428
Failed to generate ecparam file (permissions?) when writing to:
429
$out"
430
 
431
	# Explicitly return success for caller
432
	return 0
433
}
434
 
435
# Verify if Edward Curve exists
436
verify_curve_ed() {
437
	if [ "ed25519" = "$EASYRSA_CURVE" ] && "$EASYRSA_OPENSSL" genpkey -algorithm ED25519 > /dev/null; then
438
		return 0
439
	elif [ "ed448" = "$EASYRSA_CURVE" ] && "$EASYRSA_OPENSSL" genpkey -algorithm ED448 > /dev/null; then
440
		return 0
441
	fi
442
		die "Curve $EASYRSA_CURVE not found."
443
}
444
 
445
verify_ssl_lib () {
446
	# Verify EASYRSA_OPENSSL command gives expected output
447
	if [ -z "$EASYRSA_SSL_OK" ]; then
448
		val="$("$EASYRSA_OPENSSL" version)"
449
		case "${val%% *}" in
450
			OpenSSL|LibreSSL)
451
				print "\
452
Using SSL: $EASYRSA_OPENSSL $("$EASYRSA_OPENSSL" version)" ;;
453
			*) die "\
454
Missing or invalid OpenSSL
455
Expected to find openssl command at: $EASYRSA_OPENSSL" ;;
456
		esac
457
	fi
458
	EASYRSA_SSL_OK=1
459
 
460
	# Verify EASYRSA_SSL_CONF file exists
461
	[ -f "$EASYRSA_SSL_CONF" ] || die "\
462
The OpenSSL config file cannot be found.
463
Expected location: $EASYRSA_SSL_CONF"
464
} # => verify_ssl_lib ()
465
 
466
# Basic sanity-check of PKI init and complain if missing
467
verify_pki_init() {
468
	help_note="Run easyrsa without commands for usage and command help."
469
 
470
	# check that the pki dir exists
471
	vars_source_check
472
	[ -d "$EASYRSA_PKI" ] || die "\
473
EASYRSA_PKI does not exist (perhaps you need to run init-pki)?
474
Expected to find the EASYRSA_PKI at: $EASYRSA_PKI
475
$help_note"
476
 
477
	# verify expected dirs present:
478
	for i in private reqs; do
479
		[ -d "$EASYRSA_PKI/$i" ] || die "\
480
Missing expected directory: $i (perhaps you need to run init-pki?)
481
$help_note"
482
	done
483
 
484
	# verify ssl lib
485
	verify_ssl_lib
486
} # => verify_pki_init()
487
 
488
# Verify core CA files present
489
verify_ca_init() {
490
	help_note="Run without commands for usage and command help."
491
 
492
	# First check the PKI has been initialized
493
	verify_pki_init
494
 
495
	# Verify expected files are present. Allow files to be regular files
496
	# (or symlinks), but also pipes, for flexibility with ca.key
497
	for i in serial index.txt index.txt.attr ca.crt private/ca.key; do
498
		if [ ! -f "$EASYRSA_PKI/$i" ] && [ ! -p "$EASYRSA_PKI/$i" ]; then
499
			[ "$1" = "test" ] && return 1
500
			die "\
501
Missing expected CA file: $i (perhaps you need to run build-ca?)
502
$help_note"
503
		fi
504
	done
505
 
506
	# When operating in 'test' mode, return success.
507
	# test callers don't care about CA-specific dir structure
508
	[ "$1" = "test" ] && return 0
509
 
510
	# verify expected CA-specific dirs:
511
	for i in issued certs_by_serial
512
	do
513
		[ -d "$EASYRSA_PKI/$i" ] || die "\
514
Missing expected CA dir: $i (perhaps you need to run build-ca?)
515
$help_note"
516
	done
517
 
518
	# explicitly return success for callers
519
	return 0
520
 
521
} # => verify_ca_init()
522
 
523
# init-pki backend:
524
init_pki() {
525
 
526
	# If EASYRSA_PKI exists, confirm before we rm -rf (skiped with EASYRSA_BATCH)
527
	if [ -e "$EASYRSA_PKI" ]; then
528
		confirm "Confirm removal: " "yes" "
529
WARNING!!!
530
 
531
You are about to remove the EASYRSA_PKI at: $EASYRSA_PKI
532
and initialize a fresh PKI here."
533
		# now remove it:
534
		rm -rf "$EASYRSA_PKI" || die "Removal of PKI dir failed. Check/correct errors above"
535
	fi
536
 
537
	# new dirs:
538
	for i in private reqs; do
539
		mkdir -p "$EASYRSA_PKI/$i" || die "Failed to create PKI file structure (permissions?)"
540
	done
541
 
542
	# Create $EASYRSA_SAFE_CONF ($OPENSSL_CONF) prevents bogus warnings (especially useful on win32)
543
	if [ ! -f "$EASYRSA_SSL_CONF" ] && [ -f "$EASYRSA/openssl-easyrsa.cnf" ];
544
	then
545
		cp "$EASYRSA/openssl-easyrsa.cnf" "$EASYRSA_SSL_CONF"
546
		easyrsa_openssl makesafeconf
547
	fi
548
 
549
	notice "\
550
init-pki complete; you may now create a CA or requests.
551
Your newly created PKI dir is: $EASYRSA_PKI
552
"
553
	return 0
554
} # => init_pki()
555
 
556
hide_read_pass()
557
{
558
	# shellcheck disable=SC2039
559
	if stty -echo 2>/dev/null; then
560
		read -r "$@"
561
		stty echo
562
	elif (set +o echo 2>/dev/null); then
563
		set +o echo
564
		read -r "$@"
565
		set -o echo
566
	elif (echo | read -r -s 2>/dev/null) ; then
567
		read -r -s "$@"
568
	else
569
		warn "Could not disable echo. Password will be shown on screen!"
570
		read -r "$@"
571
	fi
572
} # => hide_read_pass()
573
 
574
# build-ca backend:
575
build_ca() {
576
	opts=""
577
	sub_ca=""
578
	nopass=""
579
	crypto="-aes256"
580
	while [ -n "$1" ]; do
581
		case "$1" in
582
			intca) sub_ca=1 ;;
583
			subca) sub_ca=1 ;;
584
			nopass) nopass=1 ;;
585
			*) warn "Ignoring unknown command option: '$1'" ;;
586
		esac
587
		shift
588
	done
589
 
590
	verify_pki_init
591
	[ "$EASYRSA_ALGO" = "ec" ] && verify_curve_ec
592
	[ "$EASYRSA_ALGO" = "ed" ] && verify_curve_ed
593
 
594
	# setup for the simpler intermediate CA situation and overwrite with root-CA if needed:
595
	out_file="$EASYRSA_PKI/reqs/ca.req"
596
	out_key="$EASYRSA_PKI/private/ca.key"
597
	if [ ! $sub_ca ]; then
598
		out_file="$EASYRSA_PKI/ca.crt"
599
		opts="$opts -x509 -days $EASYRSA_CA_EXPIRE "
600
	fi
601
 
602
	# Test for existing CA, and complain if already present
603
	if verify_ca_init test; then
604
		die "\
605
Unable to create a CA as you already seem to have one set up.
606
If you intended to start a new CA, run init-pki first."
607
	fi
608
	# If a private key exists here, a intermediate ca was created but not signed.
609
	# Notify the user and require a signed ca.crt or a init-pki:
610
	[ -f "$out_key" ] && \
611
		die "\
612
A CA private key exists but no ca.crt is found in your PKI dir of:
613
$EASYRSA_PKI
614
Refusing to create a new CA keypair as this operation would overwrite your
615
current CA keypair. If you intended to start a new CA, run init-pki first."
616
 
617
	# create necessary files and dirs:
618
	err_file="Unable to create necessary PKI files (permissions?)"
619
	for i in issued certs_by_serial \
620
		 revoked/certs_by_serial revoked/private_by_serial revoked/reqs_by_serial \
621
		 renewed/certs_by_serial renewed/private_by_serial renewed/reqs_by_serial;
622
	do
623
		mkdir -p "$EASYRSA_PKI/$i" || die "$err_file"
624
	done
625
	printf "" > "$EASYRSA_PKI/index.txt" || die "$err_file"
626
	printf "" > "$EASYRSA_PKI/index.txt.attr" || die "$err_file"
627
	print "01" > "$EASYRSA_PKI/serial" || die "$err_file"
628
 
629
	# Default CN only when not in global EASYRSA_BATCH mode:
630
	# shellcheck disable=SC2015
631
	[ "$EASYRSA_BATCH" ] && opts="$opts -batch" || export EASYRSA_REQ_CN="Easy-RSA CA"
632
 
633
	out_key_tmp="$(easyrsa_mktemp)" || die "Failed to create temporary file"
634
	out_file_tmp="$(easyrsa_mktemp)" || die "Failed to create temporary file"
635
	# Get password from user if necessary
636
	if [ ! $nopass ] && ( [ -z "$EASYRSA_PASSOUT" ] || [ -z "$EASYRSA_PASSIN" ] ); then
637
		out_key_pass_tmp="$(easyrsa_mktemp)" || die "Failed to create temporary file"
638
		echo
639
		printf "Enter New CA Key Passphrase: "
640
		hide_read_pass kpass
641
		echo
642
		printf "Re-Enter New CA Key Passphrase: "
643
		hide_read_pass kpass2
644
		echo
645
		# shellcheck disable=2154
646
		if [ "$kpass" = "$kpass2" ];
647
		then
648
			printf "%s" "$kpass" > "$out_key_pass_tmp"
649
		else
650
			die "Passphrases do not match."
651
		fi
652
	fi
653
 
654
	# create the CA key using AES256
655
	crypto_opts=""
656
	if [ ! $nopass ]; then
657
		crypto_opts="$crypto"
658
		[ -z "$EASYRSA_PASSOUT" ] && crypto_opts="$crypto_opts -passout file:$out_key_pass_tmp"
659
	fi
660
	if [ "$EASYRSA_ALGO" = "rsa" ]; then
661
		#shellcheck disable=SC2086
662
		"$EASYRSA_OPENSSL" genrsa -out "$out_key_tmp" $crypto_opts ${EASYRSA_PASSOUT:+-passout "$EASYRSA_PASSOUT"} "$EASYRSA_ALGO_PARAMS" || \
663
			die "Failed create CA private key"
664
	elif [ "$EASYRSA_ALGO" = "ec" ]; then
665
		#shellcheck disable=SC2086
666
		"$EASYRSA_OPENSSL" ecparam -in "$EASYRSA_ALGO_PARAMS" -genkey | \
667
			"$EASYRSA_OPENSSL" ec -out "$out_key_tmp" $crypto_opts ${EASYRSA_PASSOUT:+-passout "$EASYRSA_PASSOUT"} || \
668
			die "Failed create CA private key"
669
	elif [ "ed" = "$EASYRSA_ALGO" ]; then
670
		if [ "ed25519" = "$EASYRSA_CURVE" ]; then
671
			"$EASYRSA_OPENSSL" genpkey -algorithm ED25519  -out $out_key_tmp || \
672
			die "Failed create CA private key"
673
		elif [ "ed448" = "$EASYRSA_CURVE" ]; then
674
			"$EASYRSA_OPENSSL" genpkey -algorithm ED448 -out $out_key_tmp || \
675
			die "Failed create CA private key"
676
		fi
677
	fi
678
 
679
	# create the CA keypair:
680
	crypto_opts=""
681
	[ ! $nopass ] && [ -z "$EASYRSA_PASSIN" ] && crypto_opts="-passin file:$out_key_pass_tmp"
682
 
683
	#shellcheck disable=SC2086
684
	easyrsa_openssl req -utf8 -new -key "$out_key_tmp" \
685
		-keyout "$out_key_tmp" -out "$out_file_tmp" $crypto_opts $opts ${EASYRSA_PASSIN:+-passin "$EASYRSA_PASSIN"} || \
686
		die "Failed to build the CA"
687
 
688
	mv "$out_key_tmp" "$out_key"
689
	mv "$out_file_tmp" "$out_file"
690
	[ -f "$out_key_pass_tmp" ] && rm "$out_key_pass_tmp"
691
 
692
	# Success messages
693
	if [ $sub_ca ]; then
694
		notice "\
695
NOTE: Your intermediate CA request is at $out_file
696
and now must be sent to your parent CA for signing. Place your resulting cert
697
at $EASYRSA_PKI/ca.crt prior to signing operations.
698
"
699
	else	notice "\
700
CA creation complete and you may now import and sign cert requests.
701
Your new CA certificate file for publishing is at:
702
$out_file
703
"
704
	fi
705
	return 0
706
} # => build_ca()
707
 
708
# gen-dh backend:
709
gen_dh() {
710
	verify_pki_init
711
 
712
	out_file="$EASYRSA_PKI/dh.pem"
713
	"$EASYRSA_OPENSSL" dhparam -out "$out_file" "$EASYRSA_KEY_SIZE" || \
714
		die "Failed to build DH params"
715
	notice "\
716
DH parameters of size $EASYRSA_KEY_SIZE created at $out_file
717
"
718
	return 0
719
} # => gen_dh()
720
 
721
# gen-req backend:
722
gen_req() {
723
	# pull filename base and use as default interactive CommonName:
724
	[ -n "$1" ] || die "\
725
Error: gen-req must have a file base as the first argument.
726
Run easyrsa without commands for usage and commands."
727
	key_out="$EASYRSA_PKI/private/$1.key"
728
	req_out="$EASYRSA_PKI/reqs/$1.req"
729
	[ ! "$EASYRSA_BATCH" ] && EASYRSA_REQ_CN="$1"
730
	shift
731
 
732
	# function opts support
733
	opts=
734
	while [ -n "$1" ]; do
735
		case "$1" in
736
			nopass) opts="$opts -nodes" ;;
737
			# batch flag supports internal callers needing silent operation
738
			batch) EASYRSA_BATCH=1 ;;
739
			*) warn "Ignoring unknown command option: '$1'" ;;
740
		esac
741
		shift
742
	done
743
 
744
	verify_pki_init
745
	[ "$EASYRSA_ALGO" = "ec" ] && verify_curve_ec
746
	[ "$EASYRSA_ALGO" = "ed" ] && verify_curve_ed
747
 
748
	# don't wipe out an existing private key without confirmation
749
	[ -f "$key_out" ] && confirm "Confirm key overwrite: " "yes" "\
750
 
751
WARNING!!!
752
 
753
An existing private key was found at $key_out
754
Continuing with key generation will replace this key."
755
 
756
	# When EASYRSA_EXTRA_EXTS is defined, append it to openssl's [req] section:
757
	if [ -n "$EASYRSA_EXTRA_EXTS" ]; then
758
		# Setup & insert the extra ext data keyed by a magic line
759
		extra_exts="
760
req_extensions = req_extra
761
[ req_extra ]
762
$EASYRSA_EXTRA_EXTS"
763
		#shellcheck disable=SC2016
764
		awkscript='
765
{if ( match($0, "^#%EXTRA_EXTS%") )
766
	{ while ( getline<"/dev/stdin" ) {print} next }
767
 {print}
768
}'
769
		conf_tmp="$(easyrsa_mktemp)" || die "Failed to create temporary file"
770
		print "$extra_exts" | \
771
			awk "$awkscript" "$EASYRSA_SSL_CONF" \
772
			> "$conf_tmp" \
773
			|| die "Copying SSL config to temp file failed"
774
		# Use this new SSL config for the rest of this function
775
		EASYRSA_SSL_CONF="$conf_tmp"
776
	fi
777
 
778
	key_out_tmp="$(easyrsa_mktemp)" || die "Failed to create temporary file"
779
	req_out_tmp="$(easyrsa_mktemp)" || die "Failed to create temporary file"
780
	# generate request
781
	[ $EASYRSA_BATCH ] && opts="$opts -batch"
782
	# shellcheck disable=2086,2148
783
	algo_opts=""
784
	if [ "ed" != $EASYRSA_ALGO ];then
785
		algo_opts=" -newkey $EASYRSA_ALGO:$EASYRSA_ALGO_PARAMS "
786
	fi
787
	easyrsa_openssl req -utf8 -new $algo_opts \
788
		-keyout "$key_out_tmp" -out "$req_out_tmp" $opts ${EASYRSA_PASSOUT:+-passout "$EASYRSA_PASSOUT"} \
789
		|| die "Failed to generate request"
790
	mv "$key_out_tmp" "$key_out"
791
	mv "$req_out_tmp" "$req_out"
792
	notice "\
793
Keypair and certificate request completed. Your files are:
794
req: $req_out
795
key: $key_out
796
"
797
	return 0
798
} # => gen_req()
799
 
800
# common signing backend
801
sign_req() {
802
	crt_type="$1"
803
	opts=""
804
	req_in="$EASYRSA_PKI/reqs/$2.req"
805
	crt_out="$EASYRSA_PKI/issued/$2.crt"
806
 
807
	# Randomize Serial number
808
	if [ "$EASYRSA_RAND_SN" != "no" ];
809
	then
810
		i=""
811
		serial=""
812
		check_serial=""
813
		for i in 1 2 3 4 5; do
814
			"$EASYRSA_OPENSSL" rand -hex -out "$EASYRSA_PKI/serial" 16
815
			serial="$(cat "$EASYRSA_PKI/serial")"
816
			check_serial="$("$EASYRSA_OPENSSL" ca -config "$EASYRSA_SSL_CONF" -status "$serial" 2>&1)"
817
			case "$check_serial" in
818
				*"not present in db"*) break ;;
819
				*) continue ;;
820
			esac
821
		done
822
	fi
823
 
824
	# Support batch by internal caller:
825
	[ "$3" = "batch" ] && EASYRSA_BATCH=1
826
 
827
	verify_ca_init
828
 
829
	# Check argument sanity:
830
	[ -n "$2" ] || die "\
831
Incorrect number of arguments provided to sign-req:
832
expected 2, got $# (see command help for usage)"
833
 
834
	# Cert type must exist under the EASYRSA_EXT_DIR
835
	[ -r "$EASYRSA_EXT_DIR/$crt_type" ] || die "\
836
Unknown cert type '$crt_type'"
837
 
838
	# Request file must exist
839
	[ -f "$req_in" ] || die "\
840
No request found for the input: '$2'
841
Expected to find the request at: $req_in"
842
 
843
	# Confirm input is a cert req
844
	verify_file req "$req_in" || die "\
845
The certificate request file is not in a valid X509 request format.
846
Offending file: $req_in"
847
 
848
	# Display the request subject in an easy-to-read format
849
	# Confirm the user wishes to sign this request
850
	confirm "Confirm request details: " "yes" "
851
You are about to sign the following certificate.
852
Please check over the details shown below for accuracy. Note that this request
853
has not been cryptographically verified. Please be sure it came from a trusted
854
source or that you have verified the request checksum with the sender.
855
 
856
Request subject, to be signed as a $crt_type certificate for $EASYRSA_CERT_EXPIRE days:
857
 
858
$(display_dn req "$req_in")
859
"	# => confirm end
860
 
861
	# Generate the extensions file for this cert:
862
	ext_tmp="$(easyrsa_mktemp)" || die "Failed to create temporary file"
863
	{
864
		# Append first any COMMON file (if present) then the cert-type extensions
865
		cat "$EASYRSA_EXT_DIR/COMMON"
866
		cat "$EASYRSA_EXT_DIR/$crt_type"
867
		# copy req extensions
868
		[ "$EASYRSA_CP_EXT" ] && print "copy_extensions = copy"
869
 
870
		# Support a dynamic CA path length when present:
871
		[ "$crt_type" = "ca" ] && [ -n "$EASYRSA_SUBCA_LEN" ] && \
872
			print "basicConstraints = CA:TRUE, pathlen:$EASYRSA_SUBCA_LEN"
873
 
874
		# Deprecated Netscape extension support, if enabled
875
		if print "$EASYRSA_NS_SUPPORT" | awk_yesno; then
876
			[ -n "$EASYRSA_NS_COMMENT" ] && \
877
				print "nsComment = \"$EASYRSA_NS_COMMENT\""
878
			case "$crt_type" in
879
				serverClient)	print "nsCertType = serverClient" ;;
880
				server)		print "nsCertType = server" ;;
881
				client)		print "nsCertType = client" ;;
882
				ca)		print "nsCertType = sslCA" ;;
883
			esac
884
		fi
885
 
886
		# If type is server and no subjectAltName was requested,
887
		# add one to the extensions file
888
		if [ "$crt_type" = 'server' ] || [ "$crt_type" = 'serverClient' ];
889
		then
890
			echo "$EASYRSA_EXTRA_EXTS" | grep -q subjectAltName
891
			if [ $? -ne 0 ];
892
			then
893
				san=$(display_san req "$req_in")
894
 
895
				if [ -n "$san" ];
896
				then
897
					print "subjectAltName = $san"
898
				else
899
					default_server_san "$req_in"
900
				fi
901
			fi
902
		fi
903
 
904
		# Add any advanced extensions supplied by env-var:
905
		[ -n "$EASYRSA_EXTRA_EXTS" ] && print "$EASYRSA_EXTRA_EXTS"
906
 
907
		: # needed to keep die from inherting the above test
908
	} > "$ext_tmp" || die "\
909
Failed to create temp extension file (bad permissions?) at:
910
$ext_tmp"
911
 
912
	# sign request
913
	crt_out_tmp="$(easyrsa_mktemp)" || die "Failed to create temporary file"
914
	easyrsa_openssl ca -utf8 -in "$req_in" -out "$crt_out_tmp" \
915
		-extfile "$ext_tmp" -days "$EASYRSA_CERT_EXPIRE" -batch $opts ${EASYRSA_PASSIN:+-passin "$EASYRSA_PASSIN"} \
916
		|| die "signing failed (openssl output above may have more detail)"
917
	mv "$crt_out_tmp" "$crt_out"
918
	rm -f "$ext_tmp"
919
	notice "\
920
Certificate created at: $crt_out
921
"
922
	return 0
923
} # => sign_req()
924
 
925
# common build backend
926
# used to generate+sign in 1 step
927
build_full() {
928
	verify_ca_init
929
 
930
	# pull filename base:
931
	[ -n "$2" ] || die "\
932
Error: didn't find a file base name as the first argument.
933
Run easyrsa without commands for usage and commands."
934
	crt_type="$1" name="$2"
935
	req_out="$EASYRSA_PKI/reqs/$2.req"
936
	key_out="$EASYRSA_PKI/private/$2.key"
937
	crt_out="$EASYRSA_PKI/issued/$2.crt"
938
	shift 2
939
 
940
	# function opts support
941
	req_opts=
942
	while [ -n "$1" ]; do
943
		case "$1" in
944
			nopass) req_opts="$req_opts nopass" ;;
945
			inline) EASYRSA_INLINE=1 ;;
946
			*) warn "Ignoring unknown command option: '$1'" ;;
947
		esac
948
		shift
949
	done
950
 
951
	# abort on existing req/key/crt files
952
	err_exists="\
953
file already exists. Aborting build to avoid overwriting this file.
954
If you wish to continue, please use a different name or remove the file.
955
Matching file found at: "
956
	[ -f "$req_out" ] && die "Request $err_exists $req_out"
957
	[ -f "$key_out" ] && die "Key $err_exists $key_out"
958
	[ -f "$crt_out" ] && die "Certificate $err_exists $crt_out"
959
 
960
	# create request
961
	EASYRSA_REQ_CN="$name"
962
	#shellcheck disable=SC2086
963
	gen_req "$name" batch $req_opts
964
 
965
	# Sign it
966
	( sign_req "$crt_type" "$name" batch ) || {
967
		rm -f "$req_out" "$key_out"
968
		die "Failed to sign '$name'"
969
	}
970
 
971
	# inline it
972
	if [ $EASYRSA_INLINE ]; then
973
		inline_creds
974
	fi
975
} # => build_full()
976
 
977
# Create inline credentials file for this node
978
inline_creds ()
979
{
980
	[ -f "$EASYRSA_PKI/$EASYRSA_REQ_CN.creds" ] \
981
	&& die "Inline file exists: $EASYRSA_PKI/$EASYRSA_REQ_CN.creds"
982
	{
983
		printf "%s\n" "# $crt_type: $EASYRSA_REQ_CN"
984
		printf "%s\n" ""
985
		printf "%s\n" "<ca>"
986
		cat "$EASYRSA_PKI/ca.crt"
987
		printf "%s\n" "</ca>"
988
		printf "%s\n" ""
989
		printf "%s\n" "<cert>"
990
		cat "$crt_out"
991
		printf "%s\n" "</cert>"
992
		printf "%s\n" ""
993
		printf "%s\n" "<key>"
994
		cat "$key_out"
995
		printf "%s\n" "</key>"
996
		printf "%s\n" ""
997
	} > "$EASYRSA_PKI/$EASYRSA_REQ_CN.creds"
998
} # => inline_creds ()
999
 
1000
# revoke backend
1001
revoke() {
1002
	verify_ca_init
1003
 
1004
	# pull filename base:
1005
	[ -n "$1" ] || die "\
1006
Error: didn't find a file base name as the first argument.
1007
Run easyrsa without commands for usage and command help."
1008
	crt_in="$EASYRSA_PKI/issued/$1.crt"
1009
 
1010
	opts=""
1011
	if [ "$2" ]; then
1012
		opts="$opts -crl_reason $2"
1013
	fi
1014
 
1015
	verify_file x509 "$crt_in" || die "\
1016
Unable to revoke as the input file is not a valid certificate. Unexpected
1017
input in file: $crt_in"
1018
 
1019
	# confirm operation by displaying DN:
1020
	confirm "Continue with revocation: " "yes" "
1021
Please confirm you wish to revoke the certificate with the following subject:
1022
 
1023
$(display_dn x509 "$crt_in")
1024
"	# => confirm end
1025
 
1026
	# referenced cert must exist:
1027
	[ -f "$crt_in" ] || die "\
1028
Unable to revoke as no certificate was found. Certificate was expected
1029
at: $crt_in"
1030
 
1031
	# shellcheck disable=SC2086
1032
	easyrsa_openssl ca -utf8 -revoke "$crt_in" ${EASYRSA_PASSIN:+-passin "$EASYRSA_PASSIN"} $opts || die "\
1033
Failed to revoke certificate: revocation command failed."
1034
 
1035
	# move revoked files so we can reissue certificates with the same name
1036
	move_revoked "$1"
1037
 
1038
	notice "\
1039
IMPORTANT!!!
1040
 
1041
Revocation was successful. You must run gen-crl and upload a CRL to your
1042
infrastructure in order to prevent the revoked cert from being accepted.
1043
"	# => notice end
1044
	return 0
1045
} #= revoke()
1046
 
1047
# move-revoked
1048
# moves revoked certificates to an alternative folder
1049
# allows reissuing certificates with the same name
1050
move_revoked() {
1051
	verify_ca_init
1052
 
1053
	[ -n "$1" ] || die "\
1054
Error: didn't find a file base name as the first argument.
1055
Run easyrsa without commands for usage and command help."
1056
 
1057
	crt_in="$EASYRSA_PKI/issued/$1.crt"
1058
	key_in="$EASYRSA_PKI/private/$1.key"
1059
	req_in="$EASYRSA_PKI/reqs/$1.req"
1060
 
1061
	verify_file x509 "$crt_in" || die "\
1062
Unable to move revoked input file. The file is not a valid certificate. Unexpected
1063
input in file: $crt_in"
1064
 
1065
	if [ -e "$req_in" ]
1066
	then
1067
		verify_file req "$req_in" || die "\
1068
Unable to move request. The file is not a valid request. Unexpected
1069
input in file: $req_in"
1070
	fi
1071
 
1072
	# get the serial number of the certificate -> serial=XXXX
1073
	cert_serial="$(easyrsa_openssl x509 -in "$crt_in" -noout -serial)"
1074
	# remove the serial= part -> we only need the XXXX part
1075
	cert_serial=${cert_serial##*=}
1076
 
1077
	crt_by_serial="$EASYRSA_PKI/certs_by_serial/$cert_serial.pem"
1078
	crt_by_serial_revoked="$EASYRSA_PKI/revoked/certs_by_serial/$cert_serial.crt"
1079
	key_by_serial_revoked="$EASYRSA_PKI/revoked/private_by_serial/$cert_serial.key"
1080
	req_by_serial_revoked="$EASYRSA_PKI/revoked/reqs_by_serial/$cert_serial.req"
1081
 
1082
	# make sure revoked dirs exist
1083
	[ -d "$EASYRSA_PKI/revoked" ] || mkdir "$EASYRSA_PKI/revoked"
1084
	[ -d "$EASYRSA_PKI/revoked/certs_by_serial" ] || mkdir "$EASYRSA_PKI/revoked/certs_by_serial"
1085
	[ -d "$EASYRSA_PKI/revoked/private_by_serial" ] || mkdir "$EASYRSA_PKI/revoked/private_by_serial"
1086
	[ -d "$EASYRSA_PKI/revoked/reqs_by_serial" ] || mkdir "$EASYRSA_PKI/revoked/reqs_by_serial"
1087
 
1088
	# move crt, key and req file to revoked folders
1089
	mv "$crt_in" "$crt_by_serial_revoked"
1090
 
1091
	# only move the req if we have it
1092
	[ -e "$req_in" ] && mv "$req_in" "$req_by_serial_revoked"
1093
 
1094
	# only move the key if we have it
1095
	[ -e "$key_in" ] && mv "$key_in" "$key_by_serial_revoked"
1096
 
1097
	# move the rest of the files (p12, p7, ...)
1098
	# shellcheck disable=SC2231
1099
	for file in $EASYRSA_PKI/private/$1\.???
1100
	do
1101
		# get file extension
1102
		file_ext="${file##*.}"
1103
 
1104
		[ -f "$file" ] && mv "$file" "$EASYRSA_PKI/revoked/private_by_serial/$cert_serial.$file_ext"
1105
	done
1106
 
1107
	# remove the dublicate certificate in the certs_by_serial folder
1108
	rm "$crt_by_serial"
1109
 
1110
	return 0
1111
 
1112
} #= move_revoked()
1113
 
1114
# renew backend
1115
renew() {
1116
	verify_ca_init
1117
 
1118
	# pull filename base:
1119
	[ -n "$1" ] || die "\
1120
Error: didn't find a file base name as the first argument.
1121
Run easyrsa without commands for usage and command help."
1122
	crt_in="$EASYRSA_PKI/issued/$1.crt"
1123
 
1124
	opts=""
1125
	if [ "$2" ]; then
1126
		opts="$2"
1127
	fi
1128
 
1129
	verify_file x509 "$crt_in" || die "\
1130
Unable to renew as the input file is not a valid certificate. Unexpected
1131
input in file: $crt_in"
1132
 
1133
	# confirm operation by displaying DN:
1134
	confirm "Continue with renew: " "yes" "
1135
Please confirm you wish to renew the certificate with the following subject:
1136
 
1137
$(display_dn x509 "$crt_in")
1138
"	# => confirm end
1139
 
1140
	# referenced cert must exist:
1141
	[ -f "$crt_in" ] || die "\
1142
Unable to renew as no certificate was found. Certificate was expected
1143
at: $crt_in"
1144
 
1145
	# Check if old cert is expired or expires within 30 days
1146
	expire_date=$(
1147
		easyrsa_openssl x509 -in "$crt_in" -noout -enddate |
1148
		sed 's/^notAfter=//'
1149
		)
1150
        case $(uname 2>/dev/null) in
1151
        	"Darwin"|*"BSD")
1152
                	expire_date=$(date -j -f '%b %d %T %Y %Z' "$expire_date" +%s)
1153
                	allow_renew_date=$(date -j -v"+${EASYRSA_CERT_RENEW}d" +%s)
1154
                	;;
1155
          	*)
1156
                	# This works on Windows, too, since uname doesn't exist and this is catch-all
1157
                	expire_date=$(date -d "$expire_date" +%s)
1158
                	allow_renew_date=$(date -d "+${EASYRSA_CERT_RENEW}day" +%s)
1159
                	;;
1160
        esac
1161
 
1162
	[ "$expire_date" -lt "$allow_renew_date" ] || die "\
1163
Certificate expires in more than $EASYRSA_CERT_RENEW days.
1164
Renewal not allowed."
1165
 
1166
	# Extract certificate usage from old cert
1167
	cert_ext_key_usage=$(
1168
		easyrsa_openssl x509 -in "$crt_in" -noout -text |
1169
		sed -n "/X509v3 Extended Key Usage:/{n;s/^ *//g;p;}"
1170
		)
1171
	case $cert_ext_key_usage in
1172
		"TLS Web Client Authentication")
1173
			cert_type=client
1174
			;;
1175
		"TLS Web Server Authentication")
1176
			cert_type=server
1177
			;;
1178
		"TLS Web Server Authentication, TLS Web Client Authentication")
1179
			cert_type=serverClient
1180
			;;
1181
	esac
1182
 
1183
	# Use SAN from --subject-alt-name if set else use SAN from old cert
1184
	echo "$EASYRSA_EXTRA_EXTS" | grep -q subjectAltName || \
1185
	{
1186
		san=$(
1187
			easyrsa_openssl x509 -in "$crt_in" -noout -text |
1188
			sed -n "/X509v3 Subject Alternative Name:/{n;s/IP Address:/IP:/;s/ //g;p;}"
1189
			)
1190
		[ -n "$san" ] && export EASYRSA_EXTRA_EXTS="\
1191
$EASYRSA_EXTRA_EXTS
1192
subjectAltName = $san"
1193
	}
1194
 
1195
	# move renewed files so we can reissue certificate with the same name
1196
	# FIXME: Modify revoke() to also work on the renewed certs subdir
1197
	move_renewed "$1"
1198
 
1199
	# renew certificate
1200
	# shellcheck disable=SC2086
1201
	build_full $cert_type $1 $opts || die "\
1202
Failed to renew certificate: renew command failed."
1203
 
1204
	notice "\
1205
IMPORTANT!!!
1206
 
1207
Renew was successful.
1208
You may want to revoke the old certificate once the new one has been deployed.
1209
"	# => notice end
1210
	return 0
1211
} #= renew()
1212
 
1213
# move-renewed
1214
# moves renewed certificates to an alternative folder
1215
# allows reissuing certificates with the same name
1216
move_renewed() {
1217
	verify_ca_init
1218
 
1219
	[ -n "$1" ] || die "\
1220
Error: didn't find a file base name as the first argument.
1221
Run easyrsa without commands for usage and command help."
1222
 
1223
	crt_in="$EASYRSA_PKI/issued/$1.crt"
1224
	key_in="$EASYRSA_PKI/private/$1.key"
1225
	req_in="$EASYRSA_PKI/reqs/$1.req"
1226
 
1227
	verify_file x509 "$crt_in" || die "\
1228
Unable to move renewed input file. The file is not a valid certificate. Unexpected
1229
input in file: $crt_in"
1230
 
1231
	if [ -e "$req_in" ]
1232
	then
1233
		verify_file req "$req_in" || die "\
1234
Unable to move request. The file is not a valid request. Unexpected
1235
input in file: $req_in"
1236
	fi
1237
 
1238
	# get the serial number of the certificate -> serial=XXXX
1239
	cert_serial="$(easyrsa_openssl x509 -in "$crt_in" -noout -serial)"
1240
	# remove the serial= part -> we only need the XXXX part
1241
	cert_serial=${cert_serial##*=}
1242
 
1243
	crt_by_serial="$EASYRSA_PKI/certs_by_serial/$cert_serial.pem"
1244
	crt_by_serial_renewed="$EASYRSA_PKI/renewed/certs_by_serial/$cert_serial.crt"
1245
	key_by_serial_renewed="$EASYRSA_PKI/renewed/private_by_serial/$cert_serial.key"
1246
	req_by_serial_renewed="$EASYRSA_PKI/renewed/reqs_by_serial/$cert_serial.req"
1247
 
1248
	# make sure renewed dirs exist
1249
	[ -d "$EASYRSA_PKI/renewed" ] || mkdir "$EASYRSA_PKI/renewed"
1250
	[ -d "$EASYRSA_PKI/renewed/certs_by_serial" ] || mkdir "$EASYRSA_PKI/renewed/certs_by_serial"
1251
	[ -d "$EASYRSA_PKI/renewed/private_by_serial" ] || mkdir "$EASYRSA_PKI/renewed/private_by_serial"
1252
	[ -d "$EASYRSA_PKI/renewed/reqs_by_serial" ] || mkdir "$EASYRSA_PKI/renewed/reqs_by_serial"
1253
 
1254
	# move crt, key and req file to renewed folders
1255
	mv "$crt_in" "$crt_by_serial_renewed"
1256
 
1257
	# only move the req if we have it
1258
	[ -e "$req_in" ] && mv "$req_in" "$req_by_serial_renewed"
1259
 
1260
	# only move the key if we have it
1261
	[ -e "$key_in" ] && mv "$key_in" "$key_by_serial_renewed"
1262
 
1263
	# move the rest of the files (p12, p7, ...)
1264
	# shellcheck disable=SC2231
1265
	for file in $EASYRSA_PKI/private/$1\.???
1266
	do
1267
		# get file extension
1268
		file_ext="${file##*.}"
1269
 
1270
		[ -f "$file" ] && mv "$file" "$EASYRSA_PKI/renewed/private_by_serial/$cert_serial.$file_ext"
1271
	done
1272
 
1273
	# remove the duplicate certificate in the certs_by_serial folder
1274
	rm "$crt_by_serial"
1275
 
1276
	return 0
1277
 
1278
} #= move_renewed()
1279
 
1280
# gen-crl backend
1281
gen_crl() {
1282
	verify_ca_init
1283
 
1284
	out_file="$EASYRSA_PKI/crl.pem"
1285
	out_file_tmp="$(easyrsa_mktemp)" || die "Failed to create temporary file"
1286
	easyrsa_openssl ca -utf8 -gencrl -out "$out_file_tmp" ${EASYRSA_PASSIN:+-passin "$EASYRSA_PASSIN"} || die "\
1287
CRL Generation failed.
1288
"
1289
	mv "$out_file_tmp" "$out_file"
1290
 
1291
	notice "\
1292
An updated CRL has been created.
1293
CRL file: $out_file
1294
"
1295
	return 0
1296
} # => gen_crl()
1297
 
1298
# import-req backend
1299
import_req() {
1300
	verify_pki_init
1301
 
1302
	# pull passed paths
1303
	in_req="$1" short_name="$2"
1304
	out_req="$EASYRSA_PKI/reqs/$2.req"
1305
 
1306
	[ -n "$short_name" ] || die "\
1307
Unable to import: incorrect command syntax.
1308
Run easyrsa without commands for usage and command help."
1309
 
1310
	verify_file req "$in_req" || die "\
1311
The input file does not appear to be a certificate request. Aborting import.
1312
Offending file: $in_req"
1313
 
1314
	# destination must not exist
1315
	[ -f "$out_req" ] && die "\
1316
Unable to import the request as the destination file already exists.
1317
Please choose a different name for your imported request file.
1318
Existing file at: $out_req"
1319
 
1320
	# now import it
1321
	cp "$in_req" "$out_req"
1322
 
1323
	notice "\
1324
The request has been successfully imported with a short name of: $short_name
1325
You may now use this name to perform signing operations on this request.
1326
"
1327
	return 0
1328
} # => import_req()
1329
 
1330
# export pkcs#12 or pkcs#7
1331
export_pkcs() {
1332
	pkcs_type="$1"
1333
	shift
1334
 
1335
	[ -n "$1" ] || die "\
1336
Unable to export p12: incorrect command syntax.
1337
Run easyrsa without commands for usage and command help."
1338
 
1339
	short_name="$1"
1340
	crt_in="$EASYRSA_PKI/issued/$1.crt"
1341
	key_in="$EASYRSA_PKI/private/$1.key"
1342
	crt_ca="$EASYRSA_PKI/ca.crt"
1343
	shift
1344
 
1345
	verify_pki_init
1346
 
1347
	# opts support
1348
	want_ca=1
1349
	want_key=1
1350
	while [ -n "$1" ]; do
1351
		case "$1" in
1352
			noca) want_ca="" ;;
1353
			nokey) want_key="" ;;
1354
			*) warn "Ignoring unknown command option: '$1'" ;;
1355
		esac
1356
		shift
1357
	done
1358
 
1359
	pkcs_opts=
1360
	if [ $want_ca ]; then
1361
		verify_file x509 "$crt_ca" || die "\
1362
Unable to include CA cert in the $pkcs_type output (missing file, or use noca option.)
1363
Missing file expected at: $crt_ca"
1364
		pkcs_opts="$pkcs_opts -certfile $crt_ca"
1365
	fi
1366
 
1367
	# input files must exist
1368
	verify_file x509 "$crt_in" || die "\
1369
Unable to export $pkcs_type for short name '$short_name' without the certificate.
1370
Missing cert expected at: $crt_in"
1371
 
1372
	case "$pkcs_type" in
1373
	p12)
1374
		pkcs_out="$EASYRSA_PKI/private/$short_name.p12"
1375
 
1376
		if [ $want_key ]; then
1377
			[ -f "$key_in" ] || die "\
1378
Unable to export p12 for short name '$short_name' without the key
1379
(if you want a p12 without the private key, use nokey option.)
1380
Missing key expected at: $key_in"
1381
		else
1382
			pkcs_opts="$pkcs_opts -nokeys"
1383
		fi
1384
 
1385
		# export the p12:
1386
		# shellcheck disable=SC2086
1387
		easyrsa_openssl pkcs12 -in "$crt_in" -inkey "$key_in" -export \
1388
			-out "$pkcs_out" $pkcs_opts ${EASYRSA_PASSIN:+-passin "$EASYRSA_PASSIN"} ${EASYRSA_PASSOUT:+-passout "$EASYRSA_PASSOUT"} || die "\
1389
Export of p12 failed: see above for related openssl errors."
1390
	;;
1391
	p7)
1392
		pkcs_out="$EASYRSA_PKI/issued/$short_name.p7b"
1393
 
1394
		# export the p7:
1395
		# shellcheck disable=SC2086
1396
		easyrsa_openssl crl2pkcs7 -nocrl -certfile "$crt_in" \
1397
			-out "$pkcs_out" $pkcs_opts ${EASYRSA_PASSIN:+-passin "$EASYRSA_PASSIN"} ${EASYRSA_PASSOUT:+-passout "$EASYRSA_PASSOUT"} || die "\
1398
Export of p7 failed: see above for related openssl errors."
1399
	;;
1400
esac
1401
 
1402
	notice "\
1403
Successful export of $pkcs_type file. Your exported file is at the following
1404
location: $pkcs_out
1405
"
1406
	return 0
1407
} # => export_pkcs()
1408
 
1409
# set-pass backend
1410
set_pass() {
1411
	verify_pki_init
1412
 
1413
	# key type, supplied internally from frontend command call (rsa/ec)
1414
	key_type="$1"
1415
 
1416
	# values supplied by the user:
1417
	raw_file="$2"
1418
	file="$EASYRSA_PKI/private/$raw_file.key"
1419
	[ -n "$raw_file" ] || die "\
1420
Missing argument to 'set-$key_type-pass' command: no name/file supplied.
1421
See help output for usage details."
1422
 
1423
	# parse command options
1424
	shift 2
1425
	crypto="-aes256"
1426
	while [ -n "$1" ]; do
1427
		case "$1" in
1428
			nopass)	crypto="" ;;
1429
			file)	file="$raw_file" ;;
1430
			*)	warn "Ignoring unknown command option: '$1'" ;;
1431
		esac
1432
		shift
1433
	done
1434
 
1435
	[ -f "$file" ] || die "\
1436
Missing private key: expected to find the private key component at:
1437
$file"
1438
 
1439
	notice "\
1440
If the key is currently encrypted you must supply the decryption passphrase.
1441
${crypto:+You will then enter a new PEM passphrase for this key.$NL}"
1442
 
1443
	out_key_tmp="$(easyrsa_mktemp)" || die "Failed to create temporary file"
1444
	easyrsa_openssl "$key_type" -in "$file" -out "$out_key_tmp" $crypto ${EASYRSA_PASSIN:+-passin "$EASYRSA_PASSIN"} ${EASYRSA_PASSOUT:+-passout "$EASYRSA_PASSOUT"} || die "\
1445
Failed to change the private key passphrase. See above for possible openssl
1446
error messages."
1447
 
1448
	mv "$out_key_tmp" "$file" || die "\
1449
Failed to change the private key passphrase. See above for error messages."
1450
 
1451
	notice "Key passphrase successfully changed"
1452
 
1453
} # => set_pass()
1454
 
1455
# update-db backend
1456
update_db() {
1457
	verify_ca_init
1458
 
1459
	easyrsa_openssl ca -utf8 -updatedb || die "\
1460
Failed to perform update-db: see above for related openssl errors."
1461
	return 0
1462
} # => update_db()
1463
 
1464
display_san() {
1465
	format="$1" path="$2"
1466
 
1467
	echo "$EASYRSA_EXTRA_EXTS" | grep -q subjectAltName
1468
 
1469
	if [ $? -eq 0 ]; then
1470
		print "$(echo "$EASYRSA_EXTRA_EXTS" | grep subjectAltName | sed 's/^\s*subjectAltName\s*=\s*//')"
1471
	else
1472
		san=$(
1473
			"$EASYRSA_OPENSSL" "$format" -in "$path" -noout -text |
1474
			sed -n "/X509v3 Subject Alternative Name:/{n;s/ //g;s/IPAddress:/IP:/g;s/RegisteredID/RID/;p;}"
1475
			)
1476
 
1477
		[ -n "$san" ] && print "$san"
1478
	fi
1479
}
1480
 
1481
# display cert DN info on a req/X509, passed by full pathname
1482
display_dn() {
1483
	format="$1" path="$2"
1484
	print "$("$EASYRSA_OPENSSL" "$format" -in "$path" -noout -subject -nameopt multiline)"
1485
	san=$(display_san "$1" "$2")
1486
	if [ -n "$san" ]; then
1487
		print ""
1488
		print "X509v3 Subject Alternative Name:"
1489
		print "    $san"
1490
	fi
1491
 
1492
} # => display_dn()
1493
 
1494
# generate default SAN from req/X509, passed by full pathname
1495
default_server_san() {
1496
	path="$1"
1497
	cn=$(
1498
		easyrsa_openssl req -in "$path" -noout -subject -nameopt sep_multiline |
1499
		awk -F'=' '/^  *CN=/{print $2}'
1500
		)
1501
	echo "$cn" | grep -E -q '^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$'
1502
	#shellcheck disable=SC2181
1503
	if [ $? -eq 0 ]; then
1504
		print "subjectAltName = IP:$cn"
1505
	else
1506
		print "subjectAltName = DNS:$cn"
1507
	fi
1508
} # => default_server_san()
1509
 
1510
# verify a file seems to be a valid req/X509
1511
verify_file() {
1512
	format="$1"
1513
	path="$2"
1514
	easyrsa_openssl "$format" -in "$path" -noout 2>/dev/null || return 1
1515
	return 0
1516
} # => verify_file()
1517
 
1518
# show-* command backend
1519
# Prints req/cert details in a readable format
1520
show() {
1521
	type="$1"
1522
	name="$2"
1523
	in_file=""
1524
	format=""
1525
	[ -n "$name" ] || die "\
1526
Missing expected filename_base argument.
1527
Run easyrsa without commands for usage help."
1528
	shift 2
1529
 
1530
	# opts support
1531
	opts="-${type}opt no_pubkey,no_sigdump"
1532
	while [ -n "$1" ]; do
1533
		case "$1" in
1534
			full)
1535
				opts=""
1536
				;;
1537
			*)
1538
				warn "Ignoring unknown command option: '$1'"
1539
				;;
1540
		esac
1541
		shift
1542
	done
1543
 
1544
	# Determine cert/req type
1545
	if [ "$type" = "cert" ]; then
1546
		verify_ca_init
1547
		in_file="$EASYRSA_PKI/issued/${name}.crt"
1548
		format="x509"
1549
	else
1550
		verify_pki_init
1551
		in_file="$EASYRSA_PKI/reqs/${name}.req"
1552
		format="req"
1553
	fi
1554
 
1555
	# Verify file exists and is of the correct type
1556
	[ -f "$in_file" ] || die "\
1557
No such $type file with a basename of '$name' is present.
1558
Expected to find this file at:
1559
$in_file"
1560
	verify_file $format "$in_file" || die "\
1561
This file is not a valid $type file:
1562
$in_file"
1563
 
1564
	notice "\
1565
Showing $type details for '$name'.
1566
This file is stored at:
1567
$in_file
1568
"
1569
	easyrsa_openssl $format -in "$in_file" -noout -text\
1570
		-nameopt multiline $opts || die "\
1571
OpenSSL failure to process the input"
1572
} # => show()
1573
 
1574
# show-ca command backend
1575
# Prints CA cert details in a readable format
1576
show_ca() {
1577
	# opts support
1578
	opts="-certopt no_pubkey,no_sigdump"
1579
	while [ -n "$1" ]; do
1580
		case "$1" in
1581
			full) opts= ;;
1582
			*) warn "Ignoring unknown command option: '$1'" ;;
1583
		esac
1584
		shift
1585
	done
1586
 
1587
	verify_ca_init
1588
	in_file="$EASYRSA_PKI/ca.crt"
1589
	format="x509"
1590
 
1591
	# Verify file exists and is of the correct type
1592
	[ -f "$in_file" ] || die "\
1593
No such $type file with a basename of '$name' is present.
1594
Expected to find this file at:
1595
$in_file"
1596
	verify_file $format "$in_file" || die "\
1597
This file is not a valid $type file:
1598
$in_file"
1599
 
1600
	notice "\
1601
Showing $type details for 'ca'.
1602
This file is stored at:
1603
$in_file
1604
"
1605
	easyrsa_openssl $format -in "$in_file" -noout -text\
1606
		-nameopt multiline $opts || die "\
1607
OpenSSL failure to process the input"
1608
} # => show_ca()
1609
 
1610
# vars setup
1611
# Here sourcing of 'vars' if present occurs. If not present, defaults are used
1612
# to support running without a sourced config format
1613
vars_setup() {
1614
	# Try to locate a 'vars' file in order of location preference.
1615
	# If one is found, source it
1616
	vars=
1617
 
1618
	# set up program path
1619
	prog_file="$0"
1620
	prog_file2="$(which -- "$prog_file" 2>/dev/null)" && prog_file="$prog_file2"
1621
	prog_file2="$(readlink -f "$prog_file" 2>/dev/null)" && prog_file="$prog_file2"
1622
	prog_dir="${prog_file%/*}"
1623
	prog_vars="${prog_dir}/vars"
1624
	# set up PKI path
1625
	pki_vars="${EASYRSA_PKI:-$PWD/pki}/vars"
1626
 
1627
	# command-line path:
1628
	if [ ! -z "$EASYRSA_VARS_FILE" ]; then
1629
	  if [ ! -f "$EASYRSA_VARS_FILE" ]; then
1630
		  # If the --vars option does not point to a file, show helpful error.
1631
			die "The file '$EASYRSA_VARS_FILE' was not found."
1632
		fi
1633
		vars="$EASYRSA_VARS_FILE"
1634
	# PKI location, if present:
1635
	elif [ -f "$pki_vars" ]; then
1636
		vars="$pki_vars"
1637
	# EASYRSA, if defined:
1638
	elif [ -n "$EASYRSA" ] && [ -f "$EASYRSA/vars" ]; then
1639
		vars="$EASYRSA/vars"
1640
	# program location:
1641
	elif [ -f "$prog_vars" ]; then
1642
		vars="$prog_vars"
1643
	fi
1644
 
1645
	# If a vars file was located, source it
1646
	# If $EASYRSA_NO_VARS is defined (not blank) this is skipped
1647
	if [ -z "$EASYRSA_NO_VARS" ] && [ -n "$vars" ]; then
1648
		if grep -Eq 'EASYRSA_PASSIN|EASYRSA_PASSOUT' "$vars"; then
1649
			die "\
1650
Variable EASYRSA_PASSIN or EASYRSA_PASSOUT has been found in the configuration \
1651
file. Storing sensitive information in the configuration file is not \
1652
recommended - please remove it from there before continuing."
1653
		fi
1654
		#shellcheck disable=SC2034
1655
		EASYRSA_CALLER=1
1656
		# shellcheck disable=SC1090
1657
		. "$vars"
1658
		notice "\
1659
Note: using Easy-RSA configuration from: $vars"
1660
	fi
1661
 
1662
	# Set defaults, preferring existing env-vars if present
1663
	set_var EASYRSA		"$prog_dir"
1664
	set_var EASYRSA_OPENSSL	openssl
1665
	set_var EASYRSA_PKI	"$PWD/pki"
1666
	set_var EASYRSA_DN	cn_only
1667
	set_var EASYRSA_REQ_COUNTRY	"US"
1668
	set_var EASYRSA_REQ_PROVINCE	"California"
1669
	set_var EASYRSA_REQ_CITY	"San Francisco"
1670
	set_var EASYRSA_REQ_ORG		"Copyleft Certificate Co"
1671
	set_var EASYRSA_REQ_EMAIL	me@example.net
1672
	set_var EASYRSA_REQ_OU		"My Organizational Unit"
1673
	set_var EASYRSA_ALGO		rsa
1674
	set_var EASYRSA_KEY_SIZE	2048
1675
	set_var EASYRSA_CURVE		secp384r1
1676
	set_var EASYRSA_EC_DIR		"$EASYRSA_PKI/ecparams"
1677
	set_var EASYRSA_CA_EXPIRE	3650
1678
	set_var EASYRSA_CERT_EXPIRE	825 # new default of 36 months
1679
	set_var EASYRSA_CERT_RENEW	30
1680
	set_var EASYRSA_CRL_DAYS	180
1681
	set_var EASYRSA_NS_SUPPORT	no
1682
	set_var EASYRSA_NS_COMMENT	"Easy-RSA (3.0.7) Generated Certificate"
1683
	set_var EASYRSA_TEMP_DIR	"$EASYRSA_PKI"
1684
	set_var EASYRSA_REQ_CN		ChangeMe
1685
	set_var EASYRSA_DIGEST		sha256
1686
	set_var EASYRSA_SSL_CONF	"$EASYRSA_PKI/openssl-easyrsa.cnf"
1687
	set_var EASYRSA_SAFE_CONF	"$EASYRSA_PKI/safessl-easyrsa.cnf"
1688
	set_var EASYRSA_KDC_REALM	"CHANGEME.EXAMPLE.COM"
1689
 
1690
	# Same as above for the x509-types extensions dir
1691
	if [ -d "$EASYRSA_PKI/x509-types" ]; then
1692
		set_var EASYRSA_EXT_DIR		"$EASYRSA_PKI/x509-types"
1693
	else
1694
		#TODO: This should be removed.  Not really suitable for packaging.
1695
		set_var EASYRSA_EXT_DIR		"$EASYRSA/x509-types"
1696
	fi
1697
 
1698
	# EASYRSA_ALGO_PARAMS must be set depending on selected algo
1699
	if [ "ec" = "$EASYRSA_ALGO" ]; then
1700
		EASYRSA_ALGO_PARAMS="$EASYRSA_EC_DIR/${EASYRSA_CURVE}.pem"
1701
	elif [ "rsa" = "$EASYRSA_ALGO" ]; then
1702
		EASYRSA_ALGO_PARAMS="${EASYRSA_KEY_SIZE}"
1703
	elif [ "ed" != "$EASYRSA_ALGO" ]; then
1704
		die "Alg '$EASYRSA_ALGO' is invalid: must be 'rsa', 'ec' or 'ed' "
1705
	fi
1706
 
1707
	# Assign value to $EASYRSA_TEMP_DIR_session and work around Windows mktemp bug when parent dir is missing
1708
	if [ -z "$EASYRSA_TEMP_DIR_session" ]; then
1709
		if [ -d "$EASYRSA_TEMP_DIR" ]; then
1710
			EASYRSA_TEMP_DIR_session="$(mktemp -du "$EASYRSA_TEMP_DIR/easy-rsa-$$.XXXXXX")"
1711
		else
1712
			# If the directory does not exist then we have not run init-pki
1713
			mkdir -p "$EASYRSA_TEMP_DIR" || die "Cannot create $EASYRSA_TEMP_DIR (permission?)"
1714
			EASYRSA_TEMP_DIR_session="$(mktemp -du "$EASYRSA_TEMP_DIR/easy-rsa-$$.XXXXXX")"
1715
			rm -rf "$EASYRSA_TEMP_DIR"
1716
		fi
1717
	fi
1718
 
1719
	# Setting OPENSSL_CONF prevents bogus warnings (especially useful on win32)
1720
	export OPENSSL_CONF="$EASYRSA_SAFE_CONF"
1721
 
1722
	# Upgrade to 306: Create $EASYRSA_SSL_CONF if it does not exist but only if $EASYRSA_PKI exists.
1723
	if [ ! -f "$EASYRSA_SSL_CONF" ] && [ -f "$EASYRSA/openssl-easyrsa.cnf" ] && [ -d "$EASYRSA_PKI" ];
1724
	then
1725
		cp "$EASYRSA/openssl-easyrsa.cnf" "$EASYRSA_SSL_CONF"
1726
		easyrsa_openssl makesafeconf
1727
	fi
1728
 
1729
} # vars_setup()
1730
 
1731
# variable assignment by indirection when undefined; merely exports
1732
# the variable when it is already defined (even if currently null)
1733
# Sets $1 as the value contained in $2 and exports (may be blank)
1734
set_var() {
1735
	var=$1
1736
	shift
1737
	value="$*"
1738
	eval "export $var=\"\${$var-$value}\""
1739
} #=> set_var()
1740
 
1741
 
1742
############################################################################
1743
# Upgrade v2 PKI to v3 PKI
1744
 
1745
# You can report problems on the normal openvpn support channels:
1746
# --------------------------------------------------------------------------
1747
#   1. The Openvpn Forum: https://forums.openvpn.net/viewforum.php?f=31
1748
#   2. The #easyrsa IRC channel at freenode
1749
#   3. Info: https://community.openvpn.net/openvpn/wiki/easyrsa-upgrade
1750
# --------------------------------------------------------------------------
1751
#
1752
 
1753
up23_fail_upgrade ()
1754
{
1755
	# Replace die()
1756
	unset EASYRSA_BATCH
1757
	notice "
1758
============================================================================
1759
The update has failed but NOTHING has been lost.
1760
 
1761
ERROR: $1
1762
----------------------------------------------------------------------------
1763
 
1764
Further info:
1765
* https://community.openvpn.net/openvpn/wiki/easyrsa-upgrade#ersa-up23-fails
1766
 
1767
Easyrsa3 upgrade FAILED
1768
============================================================================
1769
"
1770
	exit 9
1771
} #=> up23_fail_upgrade ()
1772
 
1773
up23_verbose ()
1774
{
1775
	[ "$VERBOSE" ] || return 0
1776
	printf "%s\n" "$1"
1777
} #=> up23_verbose ()
1778
 
1779
up23_verify_new_pki ()
1780
{
1781
	# Fail now, before any changes are made
1782
 
1783
	up23_verbose "> Verify DEFAULT NEW PKI does not exist .."
1784
	EASYRSA_NEW_PKI="$EASYRSA/pki"
1785
	[ -d "$EASYRSA_NEW_PKI" ] \
1786
	&& up23_fail_upgrade "DEFAULT NEW PKI exists: $EASYRSA_NEW_PKI"
1787
 
1788
	up23_verbose "> Verify VERY-SAFE-PKI does not exist .."
1789
	EASYRSA_SAFE_PKI="$EASYRSA/VERY-SAFE-PKI"
1790
	[ -d "$EASYRSA_SAFE_PKI" ] \
1791
	&& up23_fail_upgrade "VERY-SAFE-PKI exists: $EASYRSA_SAFE_PKI"
1792
 
1793
	up23_verbose "> Verify openssl-easyrsa.cnf does exist .."
1794
	EASYRSA_SSL_CNFFILE="$EASYRSA/openssl-easyrsa.cnf"
1795
	[ -f "$EASYRSA_SSL_CNFFILE" ] \
1796
	|| up23_fail_upgrade "cannot find $EASYRSA_SSL_CNFFILE"
1797
 
1798
	up23_verbose "> Verify vars.example does exist .."
1799
	EASYRSA_VARSV3_EXMP="$EASYRSA/vars.example"
1800
	[ -f "$EASYRSA_VARSV3_EXMP" ] \
1801
	|| up23_fail_upgrade "cannot find $EASYRSA_VARSV3_EXMP"
1802
 
1803
	up23_verbose "> OK"
1804
	up23_verbose "  Initial dirs & files are in a workable state."
1805
} #=> up23_verify_new_pki ()
1806
 
1807
up23_verify_current_pki ()
1808
{
1809
	up23_verbose "> Verify CURRENT PKI vars .."
1810
 
1811
	# This can probably be improved
1812
	EASYRSA_NO_REM="$(grep '^set ' "$EASYRSA_VER2_VARSFILE")"
1813
 
1814
	# This list may not be complete
1815
	# Not required: DH_KEY_SIZE PKCS11_MODULE_PATH PKCS11_PIN
1816
	for i in KEY_DIR KEY_SIZE KEY_COUNTRY KEY_PROVINCE \
1817
	KEY_CITY KEY_ORG KEY_EMAIL KEY_CN KEY_NAME KEY_OU
1818
	do
1819
		# Effectively, source the v2 vars file
1820
		UNIQUE="set $i"
1821
		KEY_grep="$(printf "%s\n" "$EASYRSA_NO_REM" | grep "$UNIQUE")"
1822
		KEY_value="${KEY_grep##*=}"
1823
		set_var $i "$KEY_value"
1824
	done
1825
 
1826
	[ -d "$KEY_DIR" ] || up23_fail_upgrade "Cannot find CURRENT PKI KEY_DIR: $KEY_DIR"
1827
 
1828
	up23_verbose "> OK"
1829
	up23_verbose "  Current CURRENT PKI vars uses PKI in: $KEY_DIR"
1830
} #=> up23_verify_current_pki ()
1831
 
1832
up23_verify_current_ca ()
1833
{
1834
	up23_verbose "> Find CA .."
1835
	# $KEY_DIR is assigned in up23_verify_current_pki ()
1836
	[ -f "$KEY_DIR/ca.crt" ] \
1837
	|| up23_fail_upgrade "Cannot find current ca.crt: $KEY_DIR/ca.crt"
1838
	up23_verbose "> OK"
1839
 
1840
	# If CA is already verified then return
1841
	in_file="$KEY_DIR/ca.crt"
1842
	[ "$CURRENT_CA_IS_VERIFIED" = "$in_file" ] && return 0
1843
	format="x509"
1844
 
1845
	# Current CA is unverified
1846
	# Extract the current CA details
1847
	CA_SUBJECT="$(easyrsa_openssl $format -in "$in_file" -subject -noout -nameopt multiline)"
1848
 
1849
	# Extract individual elements
1850
	CA_countryName="$(printf "%s\n" "$CA_SUBJECT" \
1851
	| grep countryName | sed "s\`^.*=\ \`\`g")"
1852
	CA_stateOrProvinceName="$(printf "%s\n" "$CA_SUBJECT" \
1853
	| grep stateOrProvinceName | sed "s\`^.*=\ \`\`g")"
1854
	CA_localityName="$(printf "%s\n" "$CA_SUBJECT" \
1855
	| grep localityName | sed "s\`^.*=\ \`\`g")"
1856
	CA_organizationName="$(printf "%s\n" "$CA_SUBJECT" \
1857
	| grep organizationName | sed "s\`^.*=\ \`\`g")"
1858
	CA_organizationalUnitName="$(printf "%s\n" "$CA_SUBJECT" \
1859
	| grep organizationalUnitName | sed "s\`^.*=\ \`\`g")"
1860
	CA_emailAddress="$(printf "%s\n" "$CA_SUBJECT" \
1861
	| grep emailAddress | sed "s\`^.*=\ \`\`g")"
1862
 
1863
	# Match the current CA elements to the vars file settings
1864
	CA_vars_match=1
1865
	[ "$CA_countryName" = "$KEY_COUNTRY" ] || CA_vars_match=0
1866
	[ "$CA_stateOrProvinceName" = "$KEY_PROVINCE" ] || CA_vars_match=0
1867
	[ "$CA_localityName" = "$KEY_CITY" ] || CA_vars_match=0
1868
	[ "$CA_organizationName" = "$KEY_ORG" ] || CA_vars_match=0
1869
	[ "$CA_organizationalUnitName" = "$KEY_OU" ] || CA_vars_match=0
1870
	[ "$CA_emailAddress" = "$KEY_EMAIL" ] || CA_vars_match=0
1871
 
1872
	if [ "$CA_vars_match" -eq 1 ]
1873
	then
1874
		CURRENT_CA_IS_VERIFIED="partially"
1875
	else
1876
		up23_fail_upgrade "CA certificate does not match vars file settings"
1877
	fi
1878
 
1879
	opts="-certopt no_pubkey,no_sigdump"
1880
	if [ ! "$EASYRSA_BATCH" ]
1881
	then
1882
		up23_show_current_ca
1883
	elif [ "$VERBOSE" ]
1884
	then
1885
		up23_show_current_ca
1886
	fi
1887
	confirm "* Confirm CA shown above is correct: " "yes" \
1888
	"Found current CA at: $KEY_DIR/ca.crt"
1889
	CURRENT_CA_IS_VERIFIED="$in_file"
1890
} #=> up23_verify_current_ca ()
1891
 
1892
up23_show_current_ca ()
1893
{
1894
	printf "%s\n" "-------------------------------------------------------------------------"
1895
	# $opts is always set here
1896
	# shellcheck disable=SC2086
1897
	easyrsa_openssl $format -in "$in_file" -noout -text\
1898
	-nameopt multiline $opts || die "\
1899
	OpenSSL failure to process the input CA certificate: $in_file"
1900
	printf "%s\n" "-------------------------------------------------------------------------"
1901
} #=> up23_show_current_ca ()
1902
 
1903
up23_backup_current_pki ()
1904
{
1905
	up23_verbose "> Backup current PKI .."
1906
 
1907
	mkdir -p "$EASYRSA_SAFE_PKI" \
1908
	|| up23_fail_upgrade "Failed to create safe PKI dir: $EASYRSA_SAFE_PKI"
1909
 
1910
	cp -r "$KEY_DIR" "$EASYRSA_SAFE_PKI" \
1911
	|| up23_fail_upgrade "Failed to copy $KEY_DIR to $EASYRSA_SAFE_PKI"
1912
 
1913
	# EASYRSA_VER2_VARSFILE is either version 2 *nix ./vars or Win vars.bat
1914
	cp "$EASYRSA_VER2_VARSFILE" "$EASYRSA_SAFE_PKI" \
1915
	|| up23_fail_upgrade "Failed to copy $EASYRSA_VER2_VARSFILE to EASYRSA_SAFE_PKI"
1916
 
1917
	up23_verbose "> OK"
1918
	up23_verbose "  Current PKI backup created in: $EASYRSA_SAFE_PKI"
1919
} #=> up23_backup_current_pki ()
1920
 
1921
up23_create_new_pki ()
1922
{
1923
	# Dirs: renewed and revoked are created when used.
1924
	up23_verbose "> Create NEW PKI .."
1925
	up23_verbose ">> Create NEW PKI dirs .."
1926
	for i in private reqs issued certs_by_serial
1927
	do
1928
		mkdir -p "$EASYRSA_PKI/$i" \
1929
		|| up23_fail_upgrade "Failed to Create NEW PKI dir: $EASYRSA_PKI/$i"
1930
	done
1931
	up23_verbose ">> OK"
1932
 
1933
	up23_verbose ">> Copy database to NEW PKI .."
1934
	# Failure for these is not optional
1935
	# Files ignored: index.txt.old serial.old
1936
	for i in index.txt serial ca.crt index.txt.attr
1937
	do
1938
		cp "$KEY_DIR/$i" "$EASYRSA_PKI" \
1939
		|| up23_fail_upgrade "Failed to copy $KEY_DIR/$i to $EASYRSA_PKI"
1940
	done
1941
	up23_verbose ">> OK"
1942
 
1943
	up23_verbose ">> Copy current PKI to NEW PKI .."
1944
	for i in "csr.reqs" "pem.certs_by_serial" "crt.issued" "key.private" \
1945
	"p12.private" "p8.private" "p7b.issued"
1946
	do
1947
		FILE_EXT="${i%%.*}"
1948
		DEST_DIR="${i##*.}"
1949
		if ls "$KEY_DIR/"*".$FILE_EXT" > /dev/null 2>&1; then
1950
			cp "$KEY_DIR/"*".$FILE_EXT" "$EASYRSA_PKI/$DEST_DIR" \
1951
			|| up23_fail_upgrade "Failed to copy .$FILE_EXT"
1952
		else
1953
			up23_verbose "   Note: No .$FILE_EXT files found"
1954
		fi
1955
	done
1956
	up23_verbose ">> OK"
1957
	up23_verbose "> OK"
1958
 
1959
	# Todo: CRL - Or generate a new CRL on completion
1960
	up23_verbose "  New PKI created in: $EASYRSA_PKI"
1961
} #=> up23_create_new_pki ()
1962
 
1963
up23_upgrade_ca ()
1964
{
1965
	[ -d "$EASYRSA_PKI" ] || return 0
1966
	up23_verbose "> Confirm that index.txt.attr exists and 'unique_subject = no'"
1967
	if [ -f "$EASYRSA_PKI/index.txt.attr" ]
1968
	then
1969
		if grep -q 'unique_subject = no' "$EASYRSA_PKI/index.txt.attr"
1970
		then
1971
			# If index.txt.attr exists and "unique_suject = no" then do nothing
1972
			return 0
1973
		fi
1974
	else
1975
		# If index.txt.attr does not exists then do nothing
1976
		return 0
1977
	fi
1978
 
1979
	# Otherwise this is required for all easyrsa v3
1980
	#confirm "Set 'unique_subject = no' in index.txt.attr for your current CA: " \
1981
	#"yes" "This version of easyrsa requires that 'unique_subject = no' is set correctly"
1982
 
1983
	printf "%s\n" "unique_subject = no" > "$EASYRSA_PKI/index.txt.attr"
1984
	up23_verbose "> OK"
1985
	up23_verbose "  Upgraded index.txt.attr to v306+"
1986
} #=> up23_upgrade_index_txt_attr ()
1987
 
1988
up23_create_openssl_cnf ()
1989
{
1990
	up23_verbose "> OpenSSL config .."
1991
	EASYRSA_PKI_SSL_CNFFILE="$EASYRSA_PKI/openssl-easyrsa.cnf"
1992
	EASYRSA_PKI_SAFE_CNFFILE="$EASYRSA_PKI/safessl-easyrsa.cnf"
1993
	cp "$EASYRSA_SSL_CNFFILE" "$EASYRSA_PKI_SSL_CNFFILE" \
1994
	|| up23_fail_upgrade "create $EASYRSA_PKI_SSL_CNFFILE"
1995
	up23_verbose "> OK"
1996
	up23_verbose "  New OpenSSL config file created in: $EASYRSA_PKI_SSL_CNFFILE"
1997
 
1998
	# Create $EASYRSA_PKI/safessl-easyrsa.cnf
1999
	easyrsa_openssl makesafeconf
2000
	if [ -f "$EASYRSA_PKI_SAFE_CNFFILE" ]
2001
	then
2002
		up23_verbose "  New SafeSSL config file created in: $EASYRSA_PKI_SAFE_CNFFILE"
2003
	else
2004
		up23_verbose "  FAILED to create New SafeSSL config file in: $EASYRSA_PKI_SAFE_CNFFILE"
2005
	fi
2006
} #=> up23_create_openssl_cnf ()
2007
 
2008
up23_move_easyrsa2_programs ()
2009
{
2010
	# These files may not exist here
2011
	up23_verbose "> Move easyrsa2 programs to SAFE PKI .."
2012
	for i in build-ca build-dh build-inter build-key build-key-pass \
2013
	build-key-pkcs12 build-key-server build-req build-req-pass \
2014
	clean-all inherit-inter list-crl pkitool revoke-full sign-req \
2015
	whichopensslcnf build-ca-pass build-key-server-pass init-config \
2016
	make-crl revoke-crt openssl-0.9.6.cnf openssl-0.9.8.cnf \
2017
	openssl-1.0.0.cnf openssl.cnf README.txt index.txt.start \
2018
	vars.bat.sample serial.start
2019
	do
2020
		# Although unlikely, both files could exist
2021
		# EG: ./build-ca and ./build-ca.bat
2022
		NIX_FILE="$EASYRSA/$i"
2023
		WIN_FILE="$EASYRSA/$i.bat"
2024
		if [ -f "$NIX_FILE" ]
2025
		then
2026
			cp "$NIX_FILE" "$EASYRSA_SAFE_PKI" \
2027
			|| up23_fail_upgrade "copy $NIX_FILE $EASYRSA_SAFE_PKI"
2028
		fi
2029
 
2030
		if [ -f "$WIN_FILE" ]
2031
		then
2032
			cp "$WIN_FILE" "$EASYRSA_SAFE_PKI" \
2033
			|| up23_fail_upgrade "copy $WIN_FILE $EASYRSA_SAFE_PKI"
2034
		fi
2035
 
2036
		if [ ! -f "$NIX_FILE" ] && [ ! -f "$WIN_FILE" ]
2037
		then
2038
			up23_verbose "File does not exist, ignoring: $i(.bat)"
2039
		fi
2040
 
2041
	# These files are not removed on TEST run
2042
	[ "$NOSAVE" -eq 1  ] && rm -f "$NIX_FILE" "$WIN_FILE"
2043
	done
2044
 
2045
	up23_verbose "> OK"
2046
	up23_verbose "  Easyrsa2 programs successfully moved to: $EASYRSA_SAFE_PKI"
2047
} #=> up23_move_easyrsa2_programs ()
2048
 
2049
up23_build_v3_vars ()
2050
{
2051
	up23_verbose "> Build v3 vars file .."
2052
 
2053
	EASYRSA_EXT="easyrsa-upgrade-23"
2054
	EASYRSA_VARSV2_TMP="$EASYRSA/vars-v2.tmp.$EASYRSA_EXT"
2055
	rm -f "$EASYRSA_VARSV2_TMP"
2056
	EASYRSA_VARSV3_TMP="$EASYRSA/vars-v3.tmp.$EASYRSA_EXT"
2057
	rm -f "$EASYRSA_VARSV3_TMP"
2058
	EASYRSA_VARSV3_NEW="$EASYRSA/vars-v3.new.$EASYRSA_EXT"
2059
	rm -f "$EASYRSA_VARSV3_NEW"
2060
	EASYRSA_VARSV3_WRN="$EASYRSA/vars-v3.wrn.$EASYRSA_EXT"
2061
	rm -f "$EASYRSA_VARSV3_WRN"
2062
 
2063
	printf "%s\n" "\
2064
########################++++++++++#########################
2065
###                                                     ###
2066
###  WARNING: THIS FILE WAS AUTOMATICALLY GENERATED     ###
2067
###           ALL SETTINGS ARE AT THE END OF THE FILE   ###
2068
###                                                     ###
2069
########################++++++++++#########################
2070
 
2071
" > "$EASYRSA_VARSV3_WRN" || up23_fail_upgrade "Failed to create $EASYRSA_VARSV3_WRN"
2072
 
2073
	# Create vars v3 temp file from sourced vars v2 key variables
2074
	{
2075
		printf "%s\n" "set_var EASYRSA_KEY_SIZE $KEY_SIZE"
2076
		printf "%s\n" "set_var EASYRSA_REQ_COUNTRY \"$KEY_COUNTRY\""
2077
		printf "%s\n" "set_var EASYRSA_REQ_PROVINCE \"$KEY_PROVINCE\""
2078
		printf "%s\n" "set_var EASYRSA_REQ_CITY \"$KEY_CITY\""
2079
		printf "%s\n" "set_var EASYRSA_REQ_ORG \"$KEY_ORG\""
2080
		printf "%s\n" "set_var EASYRSA_REQ_EMAIL \"$KEY_EMAIL\""
2081
		printf "%s\n" "set_var EASYRSA_REQ_OU \"$KEY_OU\""
2082
		printf "%s\n" 'set_var EASYRSA_NS_SUPPORT "yes"'
2083
		printf "%s\n" 'set_var EASYRSA_DN "org"'
2084
		printf "%s\n" 'set_var EASYRSA_RAND_SN "no"'
2085
		printf "%s\n" ""
2086
	} > "$EASYRSA_VARSV3_TMP" \
2087
	|| up23_fail_upgrade "Failed to create $EASYRSA_VARSV3_TMP"
2088
 
2089
	# cat temp files into new v3 vars
2090
	cat "$EASYRSA_VARSV3_WRN" "$EASYRSA_VARSV3_EXMP" "$EASYRSA_VARSV3_TMP" \
2091
	> "$EASYRSA_VARSV3_NEW" \
2092
	|| up23_fail_upgrade "Failed to create $EASYRSA_VARSV3_NEW"
2093
 
2094
	# This file must be created and restored at the end of TEST
2095
	# for the REAL update to to succeed
2096
	EASYRSA_VARS_LIVEBKP="$EASYRSA_TARGET_VARSFILE.livebackup"
2097
	cp "$EASYRSA_VER2_VARSFILE" "$EASYRSA_VARS_LIVEBKP" \
2098
	|| up23_fail_upgrade "Failed to create $EASYRSA_VARS_LIVEBKP"
2099
	rm -f "$EASYRSA_VER2_VARSFILE"
2100
 
2101
	# "$EASYRSA_TARGET_VARSFILE" is always $EASYRSA/vars
2102
	cp "$EASYRSA_VARSV3_NEW" "$EASYRSA_TARGET_VARSFILE" \
2103
	|| up23_fail_upgrade "copy $EASYRSA_VARSV3_NEW to $EASYRSA_TARGET_VARSFILE"
2104
 
2105
	# Delete temp files
2106
	rm -f "$EASYRSA_VARSV2_TMP" "$EASYRSA_VARSV3_TMP" \
2107
	"$EASYRSA_VARSV3_NEW" "$EASYRSA_VARSV3_WRN"
2108
 
2109
	up23_verbose "> OK"
2110
	up23_verbose "  New v3 vars file created in: $EASYRSA_TARGET_VARSFILE"
2111
} #=> up23_build_v3_vars ()
2112
 
2113
up23_do_upgrade_23 ()
2114
{
2115
	up23_verbose "============================================================================"
2116
	up23_verbose "Begin ** $1 ** upgrade process .."
2117
	up23_verbose ""
2118
	up23_verbose "Easyrsa upgrade version: $EASYRSA_UPGRADE_23"
2119
	up23_verbose ""
2120
 
2121
	up23_verify_new_pki
2122
	up23_verify_current_pki
2123
	up23_verify_current_ca
2124
	up23_backup_current_pki
2125
	up23_create_new_pki
2126
	up23_upgrade_ca
2127
	up23_move_easyrsa2_programs
2128
	up23_build_v3_vars
2129
	up23_create_openssl_cnf
2130
 
2131
	if [ "$NOSAVE" -eq 0 ]
2132
	then
2133
		# Must stay in this order
2134
		# New created dirs: EASYRSA_NEW_PKI and EASYRSA_SAFE_PKI
2135
		rm -rf "$EASYRSA_NEW_PKI"
2136
		rm -rf "$EASYRSA_SAFE_PKI"
2137
		# EASYRSA_TARGET_VARSFILE is always the new created v3 vars
2138
		# Need to know if this fails
2139
		rm "$EASYRSA_TARGET_VARSFILE" \
2140
		|| up23_fail_upgrade "remove new vars file: $EASYRSA_TARGET_VARSFILE"
2141
		# EASYRSA_VER2_VARSFILE is either v2 *nix ./vars or Win vars.bat
2142
		# Need this dance because v2 vars is same name as v3 vars above
2143
		cp "$EASYRSA_VARS_LIVEBKP" "$EASYRSA_VER2_VARSFILE"
2144
	fi
2145
	rm -f "$EASYRSA_VARS_LIVEBKP"
2146
} #= up23_do_upgrade_23 ()
2147
 
2148
up23_manage_upgrade_23 ()
2149
{
2150
	EASYRSA_UPGRADE_VERSION="v1.0a (2020/01/08)"
2151
	EASYRSA_UPGRADE_TYPE="$1"
2152
 
2153
	# Verify all existing versions of vars/vars.bat
2154
	if [ -f "$vars" ]
2155
	then
2156
		if grep -q 'Complain if a user tries to do this:' "$vars"
2157
		then
2158
			EASYRSA_FOUND_VARS=1
2159
			EASYRSA_VARS_IS_VER3=1
2160
		fi
2161
 
2162
		# Easyrsa v3 does not use NOR allow use of `export`.
2163
		if grep -q 'export' "$vars"
2164
		then
2165
			EASYRSA_FOUND_VARS=1
2166
			EASYRSA_VARS_IS_VER2=1
2167
			EASYRSA_VER2_VARSFILE="$vars"
2168
			EASYRSA_TARGET_VARSFILE="$vars"
2169
		fi
2170
	fi
2171
 
2172
	if [ -f "$EASYRSA/vars.bat" ]
2173
	then
2174
		EASYRSA_FOUND_VARS=1
2175
		EASYRSA_VARS_IS_WIN2=1
2176
		EASYRSA_VER2_VARSFILE="$EASYRSA/vars.bat"
2177
		EASYRSA_TARGET_VARSFILE="$EASYRSA/vars"
2178
	fi
2179
 
2180
	[ "$EASYRSA_FOUND_VARS" ] || return 0
2181
 
2182
	# Only allow specific vars/vars.bat to exist
2183
	if [ "$EASYRSA_VARS_IS_VER3" ] && [ "$EASYRSA_VARS_IS_VER2" ]
2184
	then
2185
		die "Verify your current vars file, v3 cannot use 'export'."
2186
	fi
2187
 
2188
	if [ "$EASYRSA_VARS_IS_VER3" ] && [ "$EASYRSA_VARS_IS_WIN2" ]
2189
	then
2190
		die "Verify your current vars/vars.bat file, cannot have both."
2191
	fi
2192
 
2193
	if [ "$EASYRSA_VARS_IS_VER2" ] && [ "$EASYRSA_VARS_IS_WIN2" ]
2194
	then
2195
		die "Verify your current vars/vars.bat file, cannot have both."
2196
	fi
2197
 
2198
	# Die on invalid upgrade type or environment
2199
	if [ "$EASYRSA_UPGRADE_TYPE" = "ca" ]
2200
	then
2201
		if [ "$EASYRSA_VARS_IS_VER3" ]
2202
		then
2203
			# v3 ensure index.txt.attr "unique_subject = no"
2204
			up23_upgrade_ca
2205
			unset EASYRSA_BATCH
2206
			notice "Your CA is fully up to date."
2207
			return 0
2208
		else
2209
			die "Only v3 PKI CA can be upgraded."
2210
		fi
2211
	fi
2212
 
2213
	if [ "$EASYRSA_UPGRADE_TYPE" = "pki" ]
2214
	then
2215
		if [ "$EASYRSA_VARS_IS_VER3" ]
2216
		then
2217
			unset EASYRSA_BATCH
2218
			notice "Your PKI is fully up to date."
2219
			return 0
2220
		fi
2221
	else
2222
		die "upgrade type must be 'pki' or 'ca'."
2223
	fi
2224
 
2225
	# PKI is potentially suitable for upgrade
2226
 
2227
	warn "
2228
=========================================================================
2229
 
2230
                           * WARNING *
2231
 
2232
Found settings from EasyRSA-v2 which are not compatible with EasyRSA-v3.
2233
Before you can continue, EasyRSA must upgrade your settings and PKI.
2234
* Found EASYRSA and vars file:
2235
  $EASYRSA
2236
  $EASYRSA_VER2_VARSFILE :
2237
 
2238
Further info:
2239
* https://community.openvpn.net/openvpn/wiki/easyrsa-upgrade
2240
 
2241
Easyrsa upgrade version: $EASYRSA_UPGRADE_VERSION
2242
=========================================================================
2243
"
2244
 
2245
# Test upgrade
2246
 
2247
	NOSAVE=0
2248
 
2249
	confirm "* EasyRSA **TEST** upgrade (Changes will NOT be written): " "yes" "
2250
This upgrade will TEST that the upgrade works BEFORE making any changes."
2251
 
2252
	up23_do_upgrade_23 "TEST"
2253
 
2254
	notice "
2255
=========================================================================
2256
 
2257
                             * NOTICE *
2258
 
2259
EasyRSA upgrade **TEST** has successfully completed.
2260
"
2261
# Upgrade for REAL
2262
 
2263
	NOSAVE=1
2264
 
2265
	confirm "* EasyRSA **REAL** upgrade (Changes WILL be written): " "yes" "
2266
=========================================================================
2267
 
2268
                             * WARNING *
2269
 
2270
Run REAL upgrade: Answer yes (Once completed you will have a version 3 PKI)
2271
Terminate upgrade: Answer no (No changes have been made to your current PKI)
2272
"
2273
 
2274
	confirm "* Confirm **REAL** upgrade (Changes will be written): " "yes" "
2275
=========================================================================
2276
 
2277
                          * SECOND WARNING *
2278
 
2279
This upgrade will permanently write changes to your PKI !
2280
(With full backup backout)
2281
"
2282
	up23_do_upgrade_23 "REAL"
2283
 
2284
	notice "
2285
=========================================================================
2286
 
2287
                             * NOTICE *
2288
 
2289
Your settings and PKI have been successfully upgraded to EasyRSA version3
2290
 
2291
A backup of your current PKI is here:
2292
  $EASYRSA_SAFE_PKI
2293
 
2294
                        * IMPORTANT NOTICE *
2295
 
2296
1. YOU MUST VERIFY THAT YOUR NEW ./vars FILE IS SETUP CORRECTLY
2297
2. IF YOU ARE USING WINDOWS YOU MUST ENSURE THAT openssl IS CORRECTLY DEFINED
2298
   IN ./vars (example follows)
2299
 
2300
 #
2301
 # This sample is in Windows syntax -- edit it for your path if not using PATH:
2302
 # set_var EASYRSA_OPENSSL   \"C:/Program Files/OpenSSL-Win32/bin/openssl.exe\"
2303
 #
2304
 # Alternate location (Note: Forward slash '/' is correct for Windpws):
2305
 # set_var EASYRSA_OPENSSL   \"C:/Program Files/Openvpn/bin/openssl.exe\"
2306
 #
2307
 
2308
3. Finally, you can verify that easyrsa works by using these two commands:
2309
    ./easyrsa show-ca (Verify that your CA is intact and correct)
2310
    ./easyrsa gen-crl ((re)-generate a CRL file)
2311
 
2312
Further info:
2313
* https://community.openvpn.net/openvpn/wiki/easyrsa-upgrade"
2314
          up23_verbose "
2315
                   * UPGRADE COMPLETED SUCCESSFULLY *
2316
"
2317
 
2318
return 0
2319
 
2320
} # => up23_manage_upgrade_23 ()
2321
 
2322
 
2323
 
2324
########################################
2325
# Invocation entry point:
2326
 
2327
NL='
2328
'
2329
 
2330
# Be secure with a restrictive umask
2331
[ -z "$EASYRSA_NO_UMASK" ] && umask 077
2332
 
2333
# Parse options
2334
while :; do
2335
	# Separate option from value:
2336
	opt="${1%%=*}"
2337
	val="${1#*=}"
2338
	empty_ok="" # Empty values are not allowed unless excepted
2339
 
2340
	case "$opt" in
2341
	--days)
2342
		export EASYRSA_CERT_EXPIRE="$val"
2343
		export EASYRSA_CA_EXPIRE="$val"
2344
		export EASYRSA_CRL_DAYS="$val"
2345
		;;
2346
	--pki-dir)
2347
		export EASYRSA_PKI="$val" ;;
2348
	--use-algo)
2349
		export EASYRSA_ALGO="$val" ;;
2350
	--keysize)
2351
		export EASYRSA_KEY_SIZE="$val" ;;
2352
	--curve)
2353
		export EASYRSA_CURVE="$val" ;;
2354
	--dn-mode)
2355
		export EASYRSA_DN="$val" ;;
2356
	--req-cn)
2357
		export EASYRSA_REQ_CN="$val" ;;
2358
	--digest)
2359
		export EASYRSA_DIGEST="$val" ;;
2360
	--req-c)
2361
		empty_ok=1
2362
		export EASYRSA_REQ_COUNTRY="$val" ;;
2363
	--req-st)
2364
		empty_ok=1
2365
		export EASYRSA_REQ_PROVINCE="$val" ;;
2366
	--req-city)
2367
		empty_ok=1
2368
		export EASYRSA_REQ_CITY="$val" ;;
2369
	--req-org)
2370
		empty_ok=1
2371
		export EASYRSA_REQ_ORG="$val" ;;
2372
	--req-email)
2373
		empty_ok=1
2374
		export EASYRSA_REQ_EMAIL="$val" ;;
2375
	--req-ou)
2376
		empty_ok=1
2377
		export EASYRSA_REQ_OU="$val" ;;
2378
	--ns-cert)
2379
		export EASYRSA_NS_SUPPORT="$val" ;;
2380
	--ns-comment)
2381
		empty_ok=1
2382
		export EASYRSA_NS_COMMENT="$val" ;;
2383
	--batch)
2384
		empty_ok=1
2385
		export EASYRSA_BATCH=1 ;;
2386
	--passin)
2387
		export EASYRSA_PASSIN="$val";;
2388
	--passout)
2389
		export EASYRSA_PASSOUT="$val";;
2390
	--subca-len)
2391
		export EASYRSA_SUBCA_LEN="$val" ;;
2392
	--vars)
2393
		export EASYRSA_VARS_FILE="$val" ;;
2394
	--copy-ext)
2395
		empty_ok=1
2396
		export EASYRSA_CP_EXT=1 ;;
2397
	--subject-alt-name)
2398
		export EASYRSA_EXTRA_EXTS="\
2399
$EASYRSA_EXTRA_EXTS
2400
subjectAltName = $val" ;;
2401
	*)
2402
		break ;;
2403
	esac
2404
 
2405
	# fatal error when no value was provided
2406
	if [ ! $empty_ok ] && { [ "$val" = "$1" ] || [ -z "$val" ]; }; then
2407
		die "Missing value to option: $opt"
2408
	fi
2409
 
2410
	shift
2411
done
2412
 
2413
# Intelligent env-var detection and auto-loading:
2414
vars_setup
2415
 
2416
# Register cleanup on EXIT
2417
trap "cleanup" EXIT
2418
# When SIGHUP, SIGINT, SIGQUIT, SIGABRT and SIGTERM,
2419
# explicitly exit to signal EXIT (non-bash shells)
2420
trap "exit 1" 1
2421
trap "exit 2" 2
2422
trap "exit 3" 3
2423
trap "exit 6" 6
2424
trap "exit 14" 15
2425
 
2426
# Upgrade: EasyRSA v2.x to EasyRSA v3.x
2427
# Upgrade: EasyRSA < v3.0.6 to v3.0.6+
2428
#up23_manage_upgrade_23
2429
 
2430
# determine how we were called, then hand off to the function responsible
2431
cmd="$1"
2432
[ -n "$1" ] && shift # scrape off command
2433
case "$cmd" in
2434
	init-pki|clean-all)
2435
		init_pki "$@"
2436
		;;
2437
	build-ca)
2438
		build_ca "$@"
2439
		;;
2440
	gen-dh)
2441
		gen_dh
2442
		;;
2443
	gen-req)
2444
		gen_req "$@"
2445
		;;
2446
	sign|sign-req)
2447
		sign_req "$@"
2448
		;;
2449
	build-client-full)
2450
		build_full client "$@"
2451
		;;
2452
	build-server-full)
2453
		build_full server "$@"
2454
		;;
2455
	build-serverClient-full)
2456
		build_full serverClient "$@"
2457
		;;
2458
	gen-crl)
2459
		gen_crl
2460
		;;
2461
	revoke)
2462
		revoke "$@"
2463
		;;
2464
	renew)
2465
		renew "$@"
2466
		;;
2467
	import-req)
2468
		import_req "$@"
2469
		;;
2470
	export-p12)
2471
		export_pkcs p12 "$@"
2472
		;;
2473
	export-p7)
2474
		export_pkcs p7 "$@"
2475
		;;
2476
	set-rsa-pass)
2477
		set_pass rsa "$@"
2478
		;;
2479
	set-ec-pass)
2480
		set_pass ec "$@"
2481
		;;
2482
	update-db)
2483
		update_db
2484
		;;
2485
	show-req)
2486
		show req "$@"
2487
		;;
2488
	show-cert)
2489
		show cert "$@"
2490
		;;
2491
	show-ca)
2492
		show_ca "$@"
2493
		;;
2494
	upgrade)
2495
		up23_manage_upgrade_23 "$@"
2496
		;;
2497
	""|help|-h|--help|--usage)
2498
		cmd_help "$1"
2499
		exit 0
2500
		;;
2501
	*)
2502
		die "Unknown command '$cmd'. Run without commands for usage help."
2503
		;;
2504
esac
2505
 
2506
# vim: ft=sh nu ai sw=8 ts=8 noet