Project

General

Profile

Download (39.1 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
 * system_certmanager.php
4
 *
5
 * part of pfSense (https://www.pfsense.org)
6
 * Copyright (c) 2004-2016 Rubicon Communications, LLC (Netgate)
7
 * Copyright (c) 2008 Shrew Soft Inc
8
 * All rights reserved.
9
 *
10
 * Licensed under the Apache License, Version 2.0 (the "License");
11
 * you may not use this file except in compliance with the License.
12
 * You may obtain a copy of the License at
13
 *
14
 * http://www.apache.org/licenses/LICENSE-2.0
15
 *
16
 * Unless required by applicable law or agreed to in writing, software
17
 * distributed under the License is distributed on an "AS IS" BASIS,
18
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19
 * See the License for the specific language governing permissions and
20
 * limitations under the License.
21
 */
22

    
23
##|+PRIV
24
##|*IDENT=page-system-certmanager
25
##|*NAME=System: Certificate Manager
26
##|*DESCR=Allow access to the 'System: Certificate Manager' page.
27
##|*MATCH=system_certmanager.php*
28
##|-PRIV
29

    
30
require_once("guiconfig.inc");
31
require_once("certs.inc");
32
require_once("pfsense-utils.inc");
33

    
34
$cert_methods = array(
35
	"import" => gettext("Import an existing Certificate"),
36
	"internal" => gettext("Create an internal Certificate"),
37
	"external" => gettext("Create a Certificate Signing Request"),
38
	"sign" => gettext("Sign a Certificate Signing Request")
39
);
40

    
41
$cert_keylens = array("512", "1024", "2048", "3072", "4096", "7680", "8192", "15360", "16384");
42
$cert_types = array(
43
	"server" => "Server Certificate",
44
	"user" => "User Certificate");
45

    
46
global $cert_altname_types;
47
global $openssl_digest_algs;
48

    
49
if (isset($_REQUEST['userid']) && is_numericint($_REQUEST['userid'])) {
50
	$userid = $_REQUEST['userid'];
51
}
52

    
53
if (isset($userid)) {
54
	$cert_methods["existing"] = gettext("Choose an existing certificate");
55
	if (!is_array($config['system']['user'])) {
56
		$config['system']['user'] = array();
57
	}
58
	$a_user =& $config['system']['user'];
59
}
60

    
61
if (isset($_REQUEST['id']) && is_numericint($_REQUEST['id'])) {
62
	$id = $_REQUEST['id'];
63
}
64

    
65
if (!is_array($config['ca'])) {
66
	$config['ca'] = array();
67
}
68

    
69
$a_ca =& $config['ca'];
70

    
71
if (!is_array($config['cert'])) {
72
	$config['cert'] = array();
73
}
74

    
75
$a_cert =& $config['cert'];
76

    
77
$internal_ca_count = 0;
78
foreach ($a_ca as $ca) {
79
	if ($ca['prv']) {
80
		$internal_ca_count++;
81
	}
82
}
83

    
84
$act = $_REQUEST['act'];
85

    
86
if ($_POST['act'] == "del") {
87

    
88
	if (!isset($a_cert[$id])) {
89
		pfSenseHeader("system_certmanager.php");
90
		exit;
91
	}
92

    
93
	unset($a_cert[$id]);
94
	write_config();
95
	$savemsg = sprintf(gettext("Certificate %s successfully deleted."), htmlspecialchars($a_cert[$id]['descr']));
96
	pfSenseHeader("system_certmanager.php");
97
	exit;
98
}
99

    
100
if ($act == "new") {
101
	$pconfig['method'] = $_POST['method'];
102
	$pconfig['keylen'] = "2048";
103
	$pconfig['digest_alg'] = "sha256";
104
	$pconfig['csr_keylen'] = "2048";
105
	$pconfig['csr_digest_alg'] = "sha256";
106
	$pconfig['csrsign_digest_alg'] = "sha256";
107
	$pconfig['type'] = "user";
108
	$pconfig['lifetime'] = "3650";
109
}
110

    
111
if ($act == "exp") {
112

    
113
	if (!$a_cert[$id]) {
114
		pfSenseHeader("system_certmanager.php");
115
		exit;
116
	}
117

    
118
	$exp_name = urlencode("{$a_cert[$id]['descr']}.crt");
119
	$exp_data = base64_decode($a_cert[$id]['crt']);
120
	$exp_size = strlen($exp_data);
121

    
122
	header("Content-Type: application/octet-stream");
123
	header("Content-Disposition: attachment; filename={$exp_name}");
124
	header("Content-Length: $exp_size");
125
	echo $exp_data;
126
	exit;
127
}
128

    
129
if ($act == "req") {
130

    
131
	if (!$a_cert[$id]) {
132
		pfSenseHeader("system_certmanager.php");
133
		exit;
134
	}
135

    
136
	$exp_name = urlencode("{$a_cert[$id]['descr']}.req");
137
	$exp_data = base64_decode($a_cert[$id]['csr']);
138
	$exp_size = strlen($exp_data);
139

    
140
	header("Content-Type: application/octet-stream");
141
	header("Content-Disposition: attachment; filename={$exp_name}");
142
	header("Content-Length: $exp_size");
143
	echo $exp_data;
144
	exit;
145
}
146

    
147
if ($act == "key") {
148

    
149
	if (!$a_cert[$id]) {
150
		pfSenseHeader("system_certmanager.php");
151
		exit;
152
	}
153

    
154
	$exp_name = urlencode("{$a_cert[$id]['descr']}.key");
155
	$exp_data = base64_decode($a_cert[$id]['prv']);
156
	$exp_size = strlen($exp_data);
157

    
158
	header("Content-Type: application/octet-stream");
159
	header("Content-Disposition: attachment; filename={$exp_name}");
160
	header("Content-Length: $exp_size");
161
	echo $exp_data;
162
	exit;
163
}
164

    
165
if ($act == "p12") {
166
	if (!$a_cert[$id]) {
167
		pfSenseHeader("system_certmanager.php");
168
		exit;
169
	}
170

    
171
	$exp_name = urlencode("{$a_cert[$id]['descr']}.p12");
172
	$args = array();
173
	$args['friendly_name'] = $a_cert[$id]['descr'];
174

    
175
	$ca = lookup_ca($a_cert[$id]['caref']);
176

    
177
	if ($ca) {
178
		$args['extracerts'] = openssl_x509_read(base64_decode($ca['crt']));
179
	}
180

    
181
	$res_crt = openssl_x509_read(base64_decode($a_cert[$id]['crt']));
182
	$res_key = openssl_pkey_get_private(array(0 => base64_decode($a_cert[$id]['prv']) , 1 => ""));
183

    
184
	$exp_data = "";
185
	openssl_pkcs12_export($res_crt, $exp_data, $res_key, null, $args);
186
	$exp_size = strlen($exp_data);
187

    
188
	header("Content-Type: application/octet-stream");
189
	header("Content-Disposition: attachment; filename={$exp_name}");
190
	header("Content-Length: $exp_size");
191
	echo $exp_data;
192
	exit;
193
}
194

    
195
if ($act == "csr") {
196
	if (!$a_cert[$id]) {
197
		pfSenseHeader("system_certmanager.php");
198
		exit;
199
	}
200

    
201
	$pconfig['descr'] = $a_cert[$id]['descr'];
202
	$pconfig['csr'] = base64_decode($a_cert[$id]['csr']);
203
}
204

    
205
if ($_POST['save']) {
206

    
207
	if ($_POST['save'] == gettext("Save")) {
208
		$input_errors = array();
209
		$pconfig = $_POST;
210

    
211
		/* input validation */
212
		if ($pconfig['method'] == "sign") {
213
			$reqdfields = explode(" ",
214
				"descr catosignwith");
215
			$reqdfieldsn = array(
216
				gettext("Descriptive name"),
217
				gettext("CA to sign with"));
218

    
219
			if (($_POST['csrtosign'] === "new") &&
220
			    ((!strstr($_POST['csrpaste'], "BEGIN CERTIFICATE REQUEST") || !strstr($_POST['csrpaste'], "END CERTIFICATE REQUEST")) &&
221
			    (!strstr($_POST['csrpaste'], "BEGIN NEW CERTIFICATE REQUEST") || !strstr($_POST['csrpaste'], "END NEW CERTIFICATE REQUEST")))) {
222
				$input_errors[] = gettext("This signing request does not appear to be valid.");
223
			}
224

    
225
			if ( (($_POST['csrtosign'] === "new") && (strlen($_POST['keypaste']) > 0)) && (!strstr($_POST['keypaste'], "BEGIN PRIVATE KEY") || !strstr($_POST['keypaste'], "END PRIVATE KEY"))) {
226
				$input_errors[] = gettext("This private does not appear to be valid.");
227
				$input_errors[] = gettext("Key data field should be blank, or a valid x509 private key");
228
			}
229

    
230
		}
231

    
232
		if ($pconfig['method'] == "import") {
233
			$reqdfields = explode(" ",
234
				"descr cert key");
235
			$reqdfieldsn = array(
236
				gettext("Descriptive name"),
237
				gettext("Certificate data"),
238
				gettext("Key data"));
239
			if ($_POST['cert'] && (!strstr($_POST['cert'], "BEGIN CERTIFICATE") || !strstr($_POST['cert'], "END CERTIFICATE"))) {
240
				$input_errors[] = gettext("This certificate does not appear to be valid.");
241
			}
242

    
243
			if (cert_get_publickey($_POST['cert'], false) != cert_get_publickey($_POST['key'], false, 'prv')) {
244
				$input_errors[] = gettext("The submitted private key does not match the submitted certificate data.");
245
			}
246
		}
247

    
248
		if ($pconfig['method'] == "internal") {
249
			$reqdfields = explode(" ",
250
				"descr caref keylen type lifetime dn_country dn_state dn_city ".
251
				"dn_organization dn_email dn_commonname");
252
			$reqdfieldsn = array(
253
				gettext("Descriptive name"),
254
				gettext("Certificate authority"),
255
				gettext("Key length"),
256
				gettext("Certificate Type"),
257
				gettext("Lifetime"),
258
				gettext("Distinguished name Country Code"),
259
				gettext("Distinguished name State or Province"),
260
				gettext("Distinguished name City"),
261
				gettext("Distinguished name Organization"),
262
				gettext("Distinguished name Email Address"),
263
				gettext("Distinguished name Common Name"));
264
		}
265

    
266
		if ($pconfig['method'] == "external") {
267
			$reqdfields = explode(" ",
268
				"descr csr_keylen csr_dn_country csr_dn_state csr_dn_city ".
269
				"csr_dn_organization csr_dn_email csr_dn_commonname");
270
			$reqdfieldsn = array(
271
				gettext("Descriptive name"),
272
				gettext("Key length"),
273
				gettext("Distinguished name Country Code"),
274
				gettext("Distinguished name State or Province"),
275
				gettext("Distinguished name City"),
276
				gettext("Distinguished name Organization"),
277
				gettext("Distinguished name Email Address"),
278
				gettext("Distinguished name Common Name"));
279
		}
280

    
281
		if ($pconfig['method'] == "existing") {
282
			$reqdfields = array("certref");
283
			$reqdfieldsn = array(gettext("Existing Certificate Choice"));
284
		}
285

    
286
		$altnames = array();
287
		do_input_validation($_POST, $reqdfields, $reqdfieldsn, $input_errors);
288

    
289
		if ($pconfig['method'] != "import" && $pconfig['method'] != "existing") {
290
			/* subjectAltNames */
291
			$san_typevar = 'altname_type';
292
			$san_valuevar = 'altname_value';
293
			// This is just the blank alternate name that is added for display purposes. We don't want to validate/save it
294
			if ($_POST["{$san_valuevar}0"] == "") {
295
				unset($_POST["{$san_typevar}0"]);
296
				unset($_POST["{$san_valuevar}0"]);
297
			}
298
			foreach ($_POST as $key => $value) {
299
				$entry = '';
300
				if (!substr_compare($san_typevar, $key, 0, strlen($san_typevar))) {
301
					$entry = substr($key, strlen($san_typevar));
302
					$field = 'type';
303
				} elseif (!substr_compare($san_valuevar, $key, 0, strlen($san_valuevar))) {
304
					$entry = substr($key, strlen($san_valuevar));
305
					$field = 'value';
306
				}
307

    
308
				if (ctype_digit($entry)) {
309
					$entry++;	// Pre-bootstrap code is one-indexed, but the bootstrap code is 0-indexed
310
					$altnames[$entry][$field] = $value;
311
				}
312
			}
313

    
314
			$pconfig['altnames']['item'] = $altnames;
315

    
316
			/* Input validation for subjectAltNames */
317
			foreach ($altnames as $idx => $altname) {
318
				switch ($altname['type']) {
319
					case "DNS":
320
						if (!is_hostname($altname['value'], true)) {
321
							array_push($input_errors, "DNS subjectAltName values must be valid hostnames, FQDNs or wildcard domains.");
322
						}
323
						break;
324
					case "IP":
325
						if (!is_ipaddr($altname['value'])) {
326
							array_push($input_errors, "IP subjectAltName values must be valid IP Addresses");
327
						}
328
						break;
329
					case "email":
330
						if (empty($altname['value'])) {
331
							array_push($input_errors, "An e-mail address must be provided for this type of subjectAltName");
332
						}
333
						if (preg_match("/[\!\#\$\%\^\(\)\~\?\>\<\&\/\\\,\"\']/", $altname['value'])) {
334
							array_push($input_errors, "The e-mail provided in a subjectAltName contains invalid characters.");
335
						}
336
						break;
337
					case "URI":
338
						/* Close enough? */
339
						if (!is_URL($altname['value'])) {
340
							$input_errors[] = "URI subjectAltName types must be a valid URI";
341
						}
342
						break;
343
					default:
344
						$input_errors[] = "Unrecognized subjectAltName type.";
345
				}
346
			}
347

    
348
			/* Make sure we do not have invalid characters in the fields for the certificate */
349

    
350
			if (preg_match("/[\?\>\<\&\/\\\"\']/", $_POST['descr'])) {
351
				array_push($input_errors, "The field 'Descriptive Name' contains invalid characters.");
352
			}
353

    
354
			for ($i = 0; $i < count($reqdfields); $i++) {
355
				if (preg_match('/email/', $reqdfields[$i])) { /* dn_email or csr_dn_name */
356
					if (preg_match("/[\!\#\$\%\^\(\)\~\?\>\<\&\/\\\,\"\']/", $_POST[$reqdfields[$i]])) {
357
						array_push($input_errors, gettext("The field 'Distinguished name Email Address' contains invalid characters."));
358
					}
359
				}
360
			}
361

    
362
			if (($pconfig['method'] != "external") && isset($_POST["keylen"]) && !in_array($_POST["keylen"], $cert_keylens)) {
363
				array_push($input_errors, gettext("Please select a valid Key Length."));
364
			}
365
			if (($pconfig['method'] != "external") && !in_array($_POST["digest_alg"], $openssl_digest_algs)) {
366
				array_push($input_errors, gettext("Please select a valid Digest Algorithm."));
367
			}
368

    
369
			if (($pconfig['method'] == "external") && isset($_POST["csr_keylen"]) && !in_array($_POST["csr_keylen"], $cert_keylens)) {
370
				array_push($input_errors, gettext("Please select a valid Key Length."));
371
			}
372
			if (($pconfig['method'] == "external") && !in_array($_POST["csr_digest_alg"], $openssl_digest_algs)) {
373
				array_push($input_errors, gettext("Please select a valid Digest Algorithm."));
374
			}
375
			if (($pconfig['method'] == "sign") && !in_array($_POST["csrsign_digest_alg"], $openssl_digest_algs)) {
376
				array_push($input_errors, gettext("Please select a valid Digest Algorithm."));
377
			}
378
		}
379

    
380
		/* save modifications */
381
		if (!$input_errors) {
382

    
383
			if ($pconfig['method'] == "existing") {
384
				$cert = lookup_cert($pconfig['certref']);
385
				if ($cert && $a_user) {
386
					$a_user[$userid]['cert'][] = $cert['refid'];
387
				}
388
			} else if ($pconfig['method'] == "sign") { // Sign a CSR
389
				$csrid = lookup_cert($pconfig['csrtosign']);
390
				$ca = & lookup_ca($pconfig['catosignwith']);
391

    
392
				// Read the CSR from $config, or if a new one, from the textarea
393
				if ($pconfig['csrtosign'] === "new") {
394
					$csr = $pconfig['csrpaste'];
395
				} else {
396
					$csr = base64_decode($csrid['csr']);
397
				}
398
				if (count($altnames)) {
399
					foreach ($altnames as $altname) {
400
						$altnames_tmp[] = "{$altname['type']}:" . cert_escape_x509_chars($altname['value']);
401
					}
402
					$altname_str = implode(",", $altnames_tmp);
403
				}
404

    
405
				$n509 = csr_sign($csr, $ca, $pconfig['csrsign_lifetime'], $pconfig['type'], $altname_str, $pconfig['csrsign_digest_alg']);
406

    
407
				if ($n509) {
408
					// Gather the details required to save the new cert
409
					$newcert = array();
410
					$newcert['refid'] = uniqid();
411
					$newcert['caref'] = $pconfig['catosignwith'];
412
					$newcert['descr'] = $pconfig['descr'];
413
					$newcert['type'] = $pconfig['type'];
414
					$newcert['crt'] = base64_encode($n509);
415

    
416
					if ($pconfig['csrtosign'] === "new") {
417
						$newcert['prv'] = base64_encode($pconfig['keypaste']);
418
					} else {
419
						$newcert['prv'] = $csrid['prv'];
420
					}
421

    
422
					// Add it to the config file
423
					$config['cert'][] = $newcert;
424
				}
425

    
426
			} else {
427
				$cert = array();
428
				$cert['refid'] = uniqid();
429
				if (isset($id) && $a_cert[$id]) {
430
					$cert = $a_cert[$id];
431
				}
432

    
433
				$cert['descr'] = $pconfig['descr'];
434

    
435
				$old_err_level = error_reporting(0); /* otherwise openssl_ functions throw warnings directly to a page screwing menu tab */
436

    
437
				if ($pconfig['method'] == "import") {
438
					cert_import($cert, $pconfig['cert'], $pconfig['key']);
439
				}
440

    
441
				if ($pconfig['method'] == "internal") {
442
					$dn = array(
443
						'countryName' => $pconfig['dn_country'],
444
						'stateOrProvinceName' => cert_escape_x509_chars($pconfig['dn_state']),
445
						'localityName' => cert_escape_x509_chars($pconfig['dn_city']),
446
						'organizationName' => cert_escape_x509_chars($pconfig['dn_organization']),
447
						'emailAddress' => cert_escape_x509_chars($pconfig['dn_email']),
448
						'commonName' => cert_escape_x509_chars($pconfig['dn_commonname']));
449
					if (!empty($pconfig['dn_organizationalunit'])) {
450
						$dn['organizationalUnitName'] = cert_escape_x509_chars($pconfig['dn_organizationalunit']);
451
					}
452
					$altnames_tmp = array(cert_add_altname_type($pconfig['dn_commonname']));
453
					if (count($altnames)) {
454
						foreach ($altnames as $altname) {
455
							// The CN is added as a SAN automatically, do not add it again.
456
							if ($altname['value'] != $pconfig['dn_commonname']) {
457
								$altnames_tmp[] = "{$altname['type']}:" . cert_escape_x509_chars($altname['value']);
458
							}
459
						}
460
					}
461
					if (!empty($altnames_tmp)) {
462
						$dn['subjectAltName'] = implode(",", $altnames_tmp);
463
					}
464

    
465
					if (!cert_create($cert, $pconfig['caref'], $pconfig['keylen'], $pconfig['lifetime'], $dn, $pconfig['type'], $pconfig['digest_alg'])) {
466
						$input_errors = array();
467
						while ($ssl_err = openssl_error_string()) {
468
							if (strpos($ssl_err, 'NCONF_get_string:no value') === false) {
469
								array_push($input_errors, "openssl library returns: " . $ssl_err);
470
							}
471
						}
472
					}
473
				}
474

    
475
				if ($pconfig['method'] == "external") {
476
					$dn = array(
477
						'countryName' => $pconfig['csr_dn_country'],
478
						'stateOrProvinceName' => cert_escape_x509_chars($pconfig['csr_dn_state']),
479
						'localityName' => cert_escape_x509_chars($pconfig['csr_dn_city']),
480
						'organizationName' => cert_escape_x509_chars($pconfig['csr_dn_organization']),
481
						'emailAddress' => cert_escape_x509_chars($pconfig['csr_dn_email']),
482
						'commonName' => cert_escape_x509_chars($pconfig['csr_dn_commonname']));
483
					if (!empty($pconfig['csr_dn_organizationalunit'])) {
484
						$dn['organizationalUnitName'] = cert_escape_x509_chars($pconfig['csr_dn_organizationalunit']);
485
					}
486

    
487
					$altnames_tmp = array(cert_add_altname_type($pconfig['csr_dn_commonname']));
488
					if (count($altnames)) {
489
						foreach ($altnames as $altname) {
490
							// The CN is added as a SAN automatically, do not add it again.
491
							if ($altname['value'] != $pconfig['csr_dn_commonname']) {
492
								$altnames_tmp[] = "{$altname['type']}:" . cert_escape_x509_chars($altname['value']);
493
							}
494
						}
495
					}
496
					if (!empty($altnames_tmp)) {
497
						$dn['subjectAltName'] = implode(",", $altnames_tmp);
498
					}
499

    
500
					if (!csr_generate($cert, $pconfig['csr_keylen'], $dn, $pconfig['type'], $pconfig['csr_digest_alg'])) {
501
						$input_errors = array();
502
						while ($ssl_err = openssl_error_string()) {
503
							if (strpos($ssl_err, 'NCONF_get_string:no value') === false) {
504
								array_push($input_errors, "openssl library returns: " . $ssl_err);
505
							}
506
						}
507
					}
508
				}
509

    
510
				error_reporting($old_err_level);
511

    
512
				if (isset($id) && $a_cert[$id]) {
513
					$a_cert[$id] = $cert;
514
				} else {
515
					$a_cert[] = $cert;
516
				}
517

    
518
				if (isset($a_user) && isset($userid)) {
519
					$a_user[$userid]['cert'][] = $cert['refid'];
520
				}
521
			}
522

    
523
			if (!$input_errors) {
524
				write_config();
525
			}
526

    
527
			if ($userid && !$input_errors) {
528
				post_redirect("system_usermanager.php", array('act' => 'edit', 'userid' => $userid));
529
				exit;
530
			}
531
		}
532
	}
533

    
534
	if ($_POST['save'] == gettext("Update")) {
535
		unset($input_errors);
536
		$pconfig = $_POST;
537

    
538
		/* input validation */
539
		$reqdfields = explode(" ", "descr cert");
540
		$reqdfieldsn = array(
541
			gettext("Descriptive name"),
542
			gettext("Final Certificate data"));
543

    
544
		do_input_validation($_POST, $reqdfields, $reqdfieldsn, $input_errors);
545

    
546
		if (preg_match("/[\?\>\<\&\/\\\"\']/", $_POST['descr'])) {
547
			array_push($input_errors, "The field 'Descriptive Name' contains invalid characters.");
548
		}
549

    
550
//		old way
551
		/* make sure this csr and certificate subjects match */
552
//		$subj_csr = csr_get_subject($pconfig['csr'], false);
553
//		$subj_cert = cert_get_subject($pconfig['cert'], false);
554
//
555
//		if (!isset($_POST['ignoresubjectmismatch']) && !($_POST['ignoresubjectmismatch'] == "yes")) {
556
//			if (strcmp($subj_csr, $subj_cert)) {
557
//				$input_errors[] = sprintf(gettext("The certificate subject '%s' does not match the signing request subject."), $subj_cert);
558
//				$subject_mismatch = true;
559
//			}
560
//		}
561
		$mod_csr = cert_get_publickey($pconfig['csr'], false, 'csr');
562
		$mod_cert = cert_get_publickey($pconfig['cert'], false);
563

    
564
		if (strcmp($mod_csr, $mod_cert)) {
565
			// simply: if the moduli don't match, then the private key and public key won't match
566
			$input_errors[] = sprintf(gettext("The certificate public key does not match the signing request public key."), $subj_cert);
567
			$subject_mismatch = true;
568
		}
569

    
570
		/* save modifications */
571
		if (!$input_errors) {
572

    
573
			$cert = $a_cert[$id];
574

    
575
			$cert['descr'] = $pconfig['descr'];
576

    
577
			csr_complete($cert, $pconfig['cert']);
578

    
579
			$a_cert[$id] = $cert;
580

    
581
			write_config();
582

    
583
			pfSenseHeader("system_certmanager.php");
584
		}
585
	}
586
}
587

    
588
$pgtitle = array(gettext("System"), gettext("Certificate Manager"), gettext("Certificates"));
589
$pglinks = array("", "system_camanager.php", "system_certmanager.php");
590

    
591
if (($act == "new" || ($_POST['save'] == gettext("Save") && $input_errors)) || ($act == "csr" || ($_POST['save'] == gettext("Update") && $input_errors))) {
592
	$pgtitle[] = gettext('Edit');
593
	$pglinks[] = "@self";
594
}
595
include("head.inc");
596

    
597
if ($input_errors) {
598
	print_input_errors($input_errors);
599
}
600

    
601
if ($savemsg) {
602
	print_info_box($savemsg, 'success');
603
}
604

    
605
$tab_array = array();
606
$tab_array[] = array(gettext("CAs"), false, "system_camanager.php");
607
$tab_array[] = array(gettext("Certificates"), true, "system_certmanager.php");
608
$tab_array[] = array(gettext("Certificate Revocation"), false, "system_crlmanager.php");
609
display_top_tabs($tab_array);
610

    
611
// Load valid country codes
612
$dn_cc = array();
613
if (file_exists("/etc/ca_countries")) {
614
	$dn_cc_file=file("/etc/ca_countries");
615
	foreach ($dn_cc_file as $line) {
616
		if (preg_match('/^(\S*)\s(.*)$/', $line, $matches)) {
617
			$dn_cc[$matches[1]] = $matches[1];
618
		}
619
	}
620
}
621

    
622
if ($act == "new" || (($_POST['save'] == gettext("Save")) && $input_errors)) {
623
	$form = new Form();
624
	$form->setAction('system_certmanager.php?act=edit');
625

    
626
	if (isset($userid) && $a_user) {
627
		$form->addGlobal(new Form_Input(
628
			'userid',
629
			null,
630
			'hidden',
631
			$userid
632
		));
633
	}
634

    
635
	if (isset($id) && $a_cert[$id]) {
636
		$form->addGlobal(new Form_Input(
637
			'id',
638
			null,
639
			'hidden',
640
			$id
641
		));
642
	}
643

    
644
	$section = new Form_Section('Add/Sign a New Certificate');
645

    
646
	if (!isset($id)) {
647
		$section->addInput(new Form_Select(
648
			'method',
649
			'*Method',
650
			$pconfig['method'],
651
			$cert_methods
652
		))->toggles();
653
	}
654

    
655
	$section->addInput(new Form_Input(
656
		'descr',
657
		'*Descriptive name',
658
		'text',
659
		($a_user && empty($pconfig['descr'])) ? $a_user[$userid]['name'] : $pconfig['descr']
660
	))->addClass('toggle-existing');
661

    
662
	$form->add($section);
663

    
664
	// Return an array containing the IDs od all CAs
665
	function list_cas() {
666
		global $a_ca;
667
		$allCas = array();
668

    
669
		foreach ($a_ca as $ca) {
670
			if ($ca['prv']) {
671
				$allCas[$ca['refid']] = $ca['descr'];
672
			}
673
		}
674

    
675
		return $allCas;
676
	}
677

    
678
	// Return an array containing the IDs od all CSRs
679
	function list_csrs() {
680
		global $config;
681
		$allCsrs = array();
682

    
683
		foreach ($config['cert'] as $cert) {
684
			if ($cert['csr']) {
685
				$allCsrs[$cert['refid']] = $cert['descr'];
686
			}
687
		}
688

    
689
		return ['new' => gettext('New CSR (Paste below)')] + $allCsrs;
690
	}
691

    
692
	$section = new Form_Section('Sign CSR');
693
	$section->addClass('toggle-sign collapse');
694

    
695
	$section->AddInput(new Form_Select(
696
		'catosignwith',
697
		'*CA to sign with',
698
		$pconfig['catosignwith'],
699
		list_cas()
700
	));
701

    
702
	$section->AddInput(new Form_Select(
703
		'csrtosign',
704
		'*CSR to sign',
705
		isset($pconfig['csrtosign']) ? $pconfig['csrtosign'] : 'new',
706
		list_csrs()
707
	));
708

    
709
	$section->addInput(new Form_Textarea(
710
		'csrpaste',
711
		'CSR data',
712
		$pconfig['csrpaste']
713
	))->setHelp('Paste a Certificate Signing Request in X.509 PEM format here.');
714

    
715
	$section->addInput(new Form_Textarea(
716
		'keypaste',
717
		'Key data',
718
		$pconfig['keypaste']
719
	))->setHelp('Optionally paste a private key here. The key will be associated with the newly signed certificate in pfSense');
720

    
721
	$section->addInput(new Form_Input(
722
		'csrsign_lifetime',
723
		'*Certificate Lifetime (days)',
724
		'number',
725
		$pconfig['csrsign_lifetime'] ? $pconfig['csrsign_lifetime']:'3650'
726
	));
727
	$section->addInput(new Form_Select(
728
		'csrsign_digest_alg',
729
		'*Digest Algorithm',
730
		$pconfig['csrsign_digest_alg'],
731
		array_combine($openssl_digest_algs, $openssl_digest_algs)
732
	))->setHelp('NOTE: It is recommended to use an algorithm stronger than '.
733
		'SHA1 when possible');
734

    
735
	$form->add($section);
736

    
737
	$section = new Form_Section('Import Certificate');
738
	$section->addClass('toggle-import collapse');
739

    
740
	$section->addInput(new Form_Textarea(
741
		'cert',
742
		'*Certificate data',
743
		$pconfig['cert']
744
	))->setHelp('Paste a certificate in X.509 PEM format here.');
745

    
746
	$section->addInput(new Form_Textarea(
747
		'key',
748
		'*Private key data',
749
		$pconfig['key']
750
	))->setHelp('Paste a private key in X.509 PEM format here.');
751

    
752
	$form->add($section);
753
	$section = new Form_Section('Internal Certificate');
754
	$section->addClass('toggle-internal collapse');
755

    
756
	if (!$internal_ca_count) {
757
		$section->addInput(new Form_StaticText(
758
			'*Certificate authority',
759
			gettext('No internal Certificate Authorities have been defined. ') .
760
			gettext('An internal CA must be defined in order to create an internal certificate. ') .
761
			sprintf(gettext('%1$sCreate%2$s an internal CA.'), '<a href="system_camanager.php?act=new&amp;method=internal"> ', '</a>')
762
		));
763
	} else {
764
		$allCas = array();
765
		foreach ($a_ca as $ca) {
766
			if (!$ca['prv']) {
767
				continue;
768
			}
769

    
770
			$allCas[ $ca['refid'] ] = $ca['descr'];
771
		}
772

    
773
		$section->addInput(new Form_Select(
774
			'caref',
775
			'*Certificate authority',
776
			$pconfig['caref'],
777
			$allCas
778
		));
779
	}
780

    
781
	$section->addInput(new Form_Select(
782
		'keylen',
783
		'*Key length',
784
		$pconfig['keylen'],
785
		array_combine($cert_keylens, $cert_keylens)
786
	));
787

    
788
	$section->addInput(new Form_Select(
789
		'digest_alg',
790
		'*Digest Algorithm',
791
		$pconfig['digest_alg'],
792
		array_combine($openssl_digest_algs, $openssl_digest_algs)
793
	))->setHelp('NOTE: It is recommended to use an algorithm stronger than '.
794
		'SHA1 when possible.');
795

    
796
	$section->addInput(new Form_Input(
797
		'lifetime',
798
		'*Lifetime (days)',
799
		'number',
800
		$pconfig['lifetime']
801
	));
802

    
803
	$section->addInput(new Form_Select(
804
		'dn_country',
805
		'*Country Code',
806
		$pconfig['dn_country'],
807
		$dn_cc
808
	));
809

    
810
	$section->addInput(new Form_Input(
811
		'dn_state',
812
		'*State or Province',
813
		'text',
814
		$pconfig['dn_state'],
815
		['placeholder' => 'e.g. Texas']
816
	));
817

    
818
	$section->addInput(new Form_Input(
819
		'dn_city',
820
		'*City',
821
		'text',
822
		$pconfig['dn_city'],
823
		['placeholder' => 'e.g. Austin']
824
	));
825

    
826
	$section->addInput(new Form_Input(
827
		'dn_organization',
828
		'*Organization',
829
		'text',
830
		$pconfig['dn_organization'],
831
		['placeholder' => 'e.g. My Company Inc']
832
	));
833

    
834
	$section->addInput(new Form_Input(
835
		'dn_organizationalunit',
836
		'Organizational Unit',
837
		'text',
838
		$pconfig['dn_organizationalunit'],
839
		['placeholder' => 'e.g. My Department Name (optional)']
840
	));
841

    
842
	$section->addInput(new Form_Input(
843
		'dn_email',
844
		'*Email Address',
845
		'text',
846
		$pconfig['dn_email'],
847
		['placeholder' => 'e.g. admin@mycompany.com']
848
	));
849

    
850
	$section->addInput(new Form_Input(
851
		'dn_commonname',
852
		'*Common Name',
853
		'text',
854
		$pconfig['dn_commonname'],
855
		['placeholder' => 'e.g. www.example.com']
856
	));
857

    
858
	$form->add($section);
859
	$section = new Form_Section('External Signing Request');
860
	$section->addClass('toggle-external collapse');
861

    
862
	$section->addInput(new Form_Select(
863
		'csr_keylen',
864
		'*Key length',
865
		$pconfig['csr_keylen'],
866
		array_combine($cert_keylens, $cert_keylens)
867
	));
868

    
869
	$section->addInput(new Form_Select(
870
		'csr_digest_alg',
871
		'*Digest Algorithm',
872
		$pconfig['csr_digest_alg'],
873
		array_combine($openssl_digest_algs, $openssl_digest_algs)
874
	))->setHelp('NOTE: It is recommended to use an algorithm stronger than '.
875
		'SHA1 when possible');
876

    
877
	$section->addInput(new Form_Select(
878
		'csr_dn_country',
879
		'*Country Code',
880
		$pconfig['csr_dn_country'],
881
		$dn_cc
882
	));
883

    
884
	$section->addInput(new Form_Input(
885
		'csr_dn_state',
886
		'*State or Province',
887
		'text',
888
		$pconfig['csr_dn_state'],
889
		['placeholder' => 'e.g. Texas']
890
	));
891

    
892
	$section->addInput(new Form_Input(
893
		'csr_dn_city',
894
		'*City',
895
		'text',
896
		$pconfig['csr_dn_city'],
897
		['placeholder' => 'e.g. Austin']
898
	));
899

    
900
	$section->addInput(new Form_Input(
901
		'csr_dn_organization',
902
		'*Organization',
903
		'text',
904
		$pconfig['csr_dn_organization'],
905
		['placeholder' => 'e.g. My Company Inc']
906
	));
907

    
908
	$section->addInput(new Form_Input(
909
		'csr_dn_organizationalunit',
910
		'Organizational Unit',
911
		'text',
912
		$pconfig['csr_dn_organizationalunit'],
913
		['placeholder' => 'e.g. My Department Name (optional)']
914
	));
915

    
916
	$section->addInput(new Form_Input(
917
		'csr_dn_email',
918
		'*Email Address',
919
		'text',
920
		$pconfig['csr_dn_email'],
921
		['placeholder' => 'e.g. admin@mycompany.com']
922
	));
923

    
924
	$section->addInput(new Form_Input(
925
		'csr_dn_commonname',
926
		'*Common Name',
927
		'text',
928
		$pconfig['csr_dn_commonname'],
929
		['placeholder' => 'e.g. internal-ca']
930
	));
931

    
932
	$form->add($section);
933
	$section = new Form_Section('Choose an Existing Certificate');
934
	$section->addClass('toggle-existing collapse');
935

    
936
	$existCerts = array();
937

    
938
	foreach ($config['cert'] as $cert)	{
939
		if (is_array($config['system']['user'][$userid]['cert'])) { // Could be MIA!
940
			if (isset($userid) && in_array($cert['refid'], $config['system']['user'][$userid]['cert'])) {
941
				continue;
942
			}
943
		}
944

    
945
		$ca = lookup_ca($cert['caref']);
946
		if ($ca) {
947
			$cert['descr'] .= " (CA: {$ca['descr']})";
948
		}
949

    
950
		if (cert_in_use($cert['refid'])) {
951
			$cert['descr'] .= " (In Use)";
952
		}
953
		if (is_cert_revoked($cert)) {
954
			$cert['descr'] .= " (Revoked)";
955
		}
956

    
957
		$existCerts[ $cert['refid'] ] = $cert['descr'];
958
	}
959

    
960
	$section->addInput(new Form_Select(
961
		'certref',
962
		'*Existing Certificates',
963
		$pconfig['certref'],
964
		$existCerts
965
	));
966

    
967
	$form->add($section);
968

    
969
	$section = new Form_Section('Certificate Attributes');
970
	$section->addClass('toggle-external toggle-internal toggle-sign collapse');
971

    
972
	$section->addInput(new Form_StaticText(
973
		gettext('Attribute Notes'),
974
		'<span class="help-block">'.
975
		gettext('The following attributes are added to certificates and ' .
976
		'requests when they are created or signed. These attributes behave ' .
977
		'differently depending on the selected mode.') .
978
		'<br/><br/>' .
979
		'<span class="toggle-internal collapse">' . gettext('For Internal Certificates, these attributes are added directly to the certificate as shown.') . '</span>' .
980
		'<span class="toggle-external collapse">' .
981
		gettext('For Certificate Signing Requests, These attributes are added to the request but they may be ignored or changed by the CA that signs the request. ') .
982
		'<br/><br/>' .
983
		gettext('If this CSR will be signed using the Certificate Manager on this firewall, set the attributes when signing instead as they cannot be carried over.') . '</span>' .
984
		'<span class="toggle-sign collapse">' . gettext('When Signing a Certificate Request, existing attributes in the request cannot be copied. The attributes below will be applied to the resulting certificate.') . '</span>' .
985
		'</span>'
986
	));
987

    
988
	$section->addInput(new Form_Select(
989
		'type',
990
		'*Certificate Type',
991
		$pconfig['type'],
992
		$cert_types
993
	))->setHelp('Add type-specific usage attributes to the signed certificate.' .
994
		' Used for placing usage restrictions on, or granting abilities to, ' .
995
		'the signed certificate.');
996

    
997
	if (empty($pconfig['altnames']['item'])) {
998
		$pconfig['altnames']['item'] = array(
999
			array('type' => null, 'value' => null)
1000
		);
1001
	}
1002

    
1003
	$counter = 0;
1004
	$numrows = count($pconfig['altnames']['item']) - 1;
1005

    
1006
	foreach ($pconfig['altnames']['item'] as $item) {
1007

    
1008
		$group = new Form_Group($counter == 0 ? 'Alternative Names':'');
1009

    
1010
		$group->add(new Form_Select(
1011
			'altname_type' . $counter,
1012
			'Type',
1013
			$item['type'],
1014
			$cert_altname_types
1015
		))->setHelp(($counter == $numrows) ? 'Type':null);
1016

    
1017
		$group->add(new Form_Input(
1018
			'altname_value' . $counter,
1019
			null,
1020
			'text',
1021
			$item['value']
1022
		))->setHelp(($counter == $numrows) ? 'Value':null);
1023

    
1024
		$group->add(new Form_Button(
1025
			'deleterow' . $counter,
1026
			'Delete',
1027
			null,
1028
			'fa-trash'
1029
		))->addClass('btn-warning');
1030

    
1031
		$group->addClass('repeatable');
1032

    
1033
		$group->setHelp('Enter additional identifiers for the certificate ' .
1034
			'in this list. The Common Name field is automatically ' .
1035
			'added to the certificate as an Alternative Name. ' .
1036
			'The signing CA may ignore or change these values.');
1037

    
1038
		$section->add($group);
1039

    
1040
		$counter++;
1041
	}
1042

    
1043
	$section->addInput(new Form_Button(
1044
		'addrow',
1045
		'Add',
1046
		null,
1047
		'fa-plus'
1048
	))->addClass('btn-success');
1049

    
1050
	$form->add($section);
1051

    
1052

    
1053
	print $form;
1054

    
1055
} else if ($act == "csr" || (($_POST['save'] == gettext("Update")) && $input_errors)) {
1056
	$form = new Form(false);
1057
	$form->setAction('system_certmanager.php?act=csr');
1058

    
1059
	$section = new Form_Section("Complete Signing Request for " . $pconfig['descr']);
1060

    
1061
	$section->addInput(new Form_Input(
1062
		'descr',
1063
		'*Descriptive name',
1064
		'text',
1065
		$pconfig['descr']
1066
	));
1067

    
1068
	$section->addInput(new Form_Textarea(
1069
		'csr',
1070
		'Signing request data',
1071
		$pconfig['csr']
1072
	))->setReadonly()
1073
	  ->setWidth(7)
1074
	  ->setHelp('Copy the certificate signing data from here and forward it to a certificate authority for signing.');
1075

    
1076
	$section->addInput(new Form_Textarea(
1077
		'cert',
1078
		'*Final certificate data',
1079
		$pconfig['cert']
1080
	))->setWidth(7)
1081
	  ->setHelp('Paste the certificate received from the certificate authority here.');
1082

    
1083
	 if (isset($id) && $a_cert[$id]) {
1084
		 $section->addInput(new Form_Input(
1085
			'id',
1086
			null,
1087
			'hidden',
1088
			$id
1089
		 ));
1090

    
1091
		 $section->addInput(new Form_Input(
1092
			'act',
1093
			null,
1094
			'hidden',
1095
			'csr'
1096
		 ));
1097
	 }
1098

    
1099
	$form->add($section);
1100

    
1101
	$form->addGlobal(new Form_Button(
1102
		'save',
1103
		'Update',
1104
		null,
1105
		'fa-save'
1106
	))->addClass('btn-primary');
1107

    
1108
	print($form);
1109
} else {
1110
?>
1111
<div class="panel panel-default">
1112
	<div class="panel-heading"><h2 class="panel-title"><?=gettext('Certificates')?></h2></div>
1113
	<div class="panel-body">
1114
		<div class="table-responsive">
1115
		<table class="table table-striped table-hover">
1116
			<thead>
1117
				<tr>
1118
					<th><?=gettext("Name")?></th>
1119
					<th><?=gettext("Issuer")?></th>
1120
					<th><?=gettext("Distinguished Name")?></th>
1121
					<th><?=gettext("In Use")?></th>
1122

    
1123
					<th class="col-sm-2"><?=gettext("Actions")?></th>
1124
				</tr>
1125
			</thead>
1126
			<tbody>
1127
<?php
1128

    
1129
$pluginparams = array();
1130
$pluginparams['type'] = 'certificates';
1131
$pluginparams['event'] = 'used_certificates';
1132
$certificates_used_by_packages = pkg_call_plugins('plugin_certificates', $pluginparams);
1133
$i = 0;
1134
foreach ($a_cert as $i => $cert):
1135
	$name = htmlspecialchars($cert['descr']);
1136
	$sans = array();
1137
	if ($cert['crt']) {
1138
		$subj = cert_get_subject($cert['crt']);
1139
		$issuer = cert_get_issuer($cert['crt']);
1140
		$purpose = cert_get_purpose($cert['crt']);
1141
		$sans = cert_get_sans($cert['crt']);
1142
		list($startdate, $enddate) = cert_get_dates($cert['crt']);
1143

    
1144
		if ($subj == $issuer) {
1145
			$caname = '<i>'. gettext("self-signed") .'</i>';
1146
		} else {
1147
			$caname = '<i>'. gettext("external").'</i>';
1148
		}
1149

    
1150
		$subj = htmlspecialchars(cert_escape_x509_chars($subj, true));
1151
	} else {
1152
		$subj = "";
1153
		$issuer = "";
1154
		$purpose = "";
1155
		$startdate = "";
1156
		$enddate = "";
1157
		$caname = "<em>" . gettext("private key only") . "</em>";
1158
	}
1159

    
1160
	if ($cert['csr']) {
1161
		$subj = htmlspecialchars(cert_escape_x509_chars(csr_get_subject($cert['csr']), true));
1162
		$sans = cert_get_sans($cert['crt']);
1163
		$caname = "<em>" . gettext("external - signature pending") . "</em>";
1164
	}
1165

    
1166
	$ca = lookup_ca($cert['caref']);
1167
	if ($ca) {
1168
		$caname = $ca['descr'];
1169
	}
1170
?>
1171
				<tr>
1172
					<td>
1173
						<?=$name?><br />
1174
						<?php if ($cert['type']): ?>
1175
							<i><?=$cert_types[$cert['type']]?></i><br />
1176
						<?php endif?>
1177
						<?php if (is_array($purpose)): ?>
1178
							CA: <b><?=$purpose['ca']?></b><br/>
1179
							<?=gettext("Server")?>: <b><?=$purpose['server']?></b><br/>
1180
						<?php endif?>
1181
					</td>
1182
					<td><?=$caname?></td>
1183
					<td>
1184
						<?=$subj?>
1185
						<?php
1186
						$certextinfo = "";
1187
						$certserial = cert_get_serial($cert['crt']);
1188
						if (!empty($certserial)) {
1189
							$certextinfo .= '<b>' . gettext("Serial: ") . '</b> ';
1190
							$certextinfo .= htmlspecialchars(cert_escape_x509_chars($certserial, true));
1191
							$certextinfo .= '<br/>';
1192
						}
1193
						$certsig = cert_get_sigtype($cert['crt']);
1194
						if (is_array($certsig) && !empty($certsig) && !empty($certsig['shortname'])) {
1195
							$certextinfo .= '<b>' . gettext("Signature Digest: ") . '</b> ';
1196
							$certextinfo .= htmlspecialchars(cert_escape_x509_chars($certsig['shortname'], true));
1197
							$certextinfo .= '<br/>';
1198
						}
1199
						if (is_array($sans) && !empty($sans)) {
1200
							$certextinfo .= '<b>' . gettext("SAN: ") . '</b> ';
1201
							$certextinfo .= htmlspecialchars(implode(', ', cert_escape_x509_chars($sans, true)));
1202
							$certextinfo .= '<br/>';
1203
						}
1204
						if (is_array($purpose) && !empty($purpose['ku'])) {
1205
							$certextinfo .= '<b>' . gettext("KU: ") . '</b> ';
1206
							$certextinfo .= htmlspecialchars(implode(', ', $purpose['ku']));
1207
							$certextinfo .= '<br/>';
1208
						}
1209
						if (is_array($purpose) && !empty($purpose['eku'])) {
1210
							$certextinfo .= '<b>' . gettext("EKU: ") . '</b> ';
1211
							$certextinfo .= htmlspecialchars(implode(', ', $purpose['eku']));
1212
						}
1213
						?>
1214
						<?php if (!empty($certextinfo)): ?>
1215
							<div class="infoblock">
1216
							<? print_info_box($certextinfo, 'info', false); ?>
1217
							</div>
1218
						<?php endif?>
1219

    
1220
						<?php if (!empty($startdate) || !empty($enddate)): ?>
1221
						<br />
1222
						<small>
1223
							<?=gettext("Valid From")?>: <b><?=$startdate ?></b><br /><?=gettext("Valid Until")?>: <b><?=$enddate ?></b>
1224
						</small>
1225
						<?php endif?>
1226
					</td>
1227
					<td>
1228
						<?php if (is_cert_revoked($cert)): ?>
1229
							<i><?=gettext("Revoked")?></i>
1230
						<?php endif?>
1231
						<?php if (is_webgui_cert($cert['refid'])): ?>
1232
							<?=gettext("webConfigurator")?>
1233
						<?php endif?>
1234
						<?php if (is_user_cert($cert['refid'])): ?>
1235
							<?=gettext("User Cert")?>
1236
						<?php endif?>
1237
						<?php if (is_openvpn_server_cert($cert['refid'])): ?>
1238
							<?=gettext("OpenVPN Server")?>
1239
						<?php endif?>
1240
						<?php if (is_openvpn_client_cert($cert['refid'])): ?>
1241
							<?=gettext("OpenVPN Client")?>
1242
						<?php endif?>
1243
						<?php if (is_ipsec_cert($cert['refid'])): ?>
1244
							<?=gettext("IPsec Tunnel")?>
1245
						<?php endif?>
1246
						<?php if (is_captiveportal_cert($cert['refid'])): ?>
1247
							<?=gettext("Captive Portal")?>
1248
						<?php endif?>
1249
						<?php echo cert_usedby_description($cert['refid'], $certificates_used_by_packages); ?>
1250
					</td>
1251
					<td>
1252
						<?php if (!$cert['csr']): ?>
1253
							<a href="system_certmanager.php?act=exp&amp;id=<?=$i?>" class="fa fa-certificate" title="<?=gettext("Export Certificate")?>"></a>
1254
							<?php if ($cert['prv']): ?>
1255
								<a href="system_certmanager.php?act=key&amp;id=<?=$i?>" class="fa fa-key" title="<?=gettext("Export Key")?>"></a>
1256
							<?php endif?>
1257
							<a href="system_certmanager.php?act=p12&amp;id=<?=$i?>" class="fa fa-archive" title="<?=gettext("Export P12")?>"></a>
1258
						<?php else: ?>
1259
							<a href="system_certmanager.php?act=csr&amp;id=<?=$i?>" class="fa fa-pencil" title="<?=gettext("Update CSR")?>"></a>
1260
							<a href="system_certmanager.php?act=req&amp;id=<?=$i?>" class="fa fa-sign-in" title="<?=gettext("Export Request")?>"></a>
1261
							<a href="system_certmanager.php?act=key&amp;id=<?=$i?>" class="fa fa-key" title="<?=gettext("Export Key")?>"></a>
1262
						<?php endif?>
1263
						<?php if (!cert_in_use($cert['refid'])): ?>
1264
							<a href="system_certmanager.php?act=del&amp;id=<?=$i?>" class="fa fa-trash" title="<?=gettext("Delete Certificate")?>" usepost></a>
1265
						<?php endif?>
1266
					</td>
1267
				</tr>
1268
<?php
1269
	$i++;
1270
	endforeach; ?>
1271
			</tbody>
1272
		</table>
1273
		</div>
1274
	</div>
1275
</div>
1276

    
1277
<nav class="action-buttons">
1278
	<a href="?act=new" class="btn btn-success btn-sm">
1279
		<i class="fa fa-plus icon-embed-btn"></i>
1280
		<?=gettext("Add/Sign")?>
1281
	</a>
1282
</nav>
1283
<?php
1284
	include("foot.inc");
1285
	exit;
1286
}
1287

    
1288

    
1289
?>
1290
<script type="text/javascript">
1291
//<![CDATA[
1292
events.push(function() {
1293

    
1294
<?php if ($internal_ca_count): ?>
1295
	function internalca_change() {
1296

    
1297
		caref = $('#caref').val();
1298

    
1299
		switch (caref) {
1300
<?php
1301
			foreach ($a_ca as $ca):
1302
				if (!$ca['prv']) {
1303
					continue;
1304
				}
1305

    
1306
				$subject = cert_get_subject_array($ca['crt']);
1307
?>
1308
				case "<?=$ca['refid'];?>":
1309
					$('#dn_country').val(<?=json_encode(cert_escape_x509_chars($subject[0]['v'], true));?>);
1310
					$('#dn_state').val(<?=json_encode(cert_escape_x509_chars($subject[1]['v'], true));?>);
1311
					$('#dn_city').val(<?=json_encode(cert_escape_x509_chars($subject[2]['v'], true));?>);
1312
					$('#dn_organization').val(<?=json_encode(cert_escape_x509_chars($subject[3]['v'], true));?>);
1313
					$('#dn_email').val(<?=json_encode(cert_escape_x509_chars($subject[4]['v'], true));?>);
1314
					$('#dn_organizationalunit').val(<?=json_encode(cert_escape_x509_chars($subject[6]['v'], true));?>);
1315
					break;
1316
<?php
1317
			endforeach;
1318
?>
1319
		}
1320
	}
1321

    
1322
	function set_csr_ro() {
1323
		var newcsr = ($('#csrtosign').val() == "new");
1324

    
1325
		$('#csrpaste').attr('readonly', !newcsr);
1326
		$('#keypaste').attr('readonly', !newcsr);
1327
		setRequired('csrpaste', newcsr);
1328
	}
1329

    
1330
	// ---------- Click checkbox handlers ---------------------------------------------------------
1331

    
1332
	$('#caref').on('change', function() {
1333
		internalca_change();
1334
	});
1335

    
1336
	$('#csrtosign').change(function () {
1337
		set_csr_ro();
1338
	});
1339

    
1340
	// ---------- On initial page load ------------------------------------------------------------
1341

    
1342
	internalca_change();
1343
	set_csr_ro();
1344

    
1345
	// Suppress "Delete row" button if there are fewer than two rows
1346
	checkLastRow();
1347

    
1348
<?php endif; ?>
1349

    
1350

    
1351
});
1352
//]]>
1353
</script>
1354
<?php
1355
include('foot.inc');
(196-196/228)