Project

General

Profile

Download (38.5 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-2019 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
	"internal" => gettext("Create an internal Certificate"),
36
	"import" => gettext("Import an existing Certificate"),
37
	"external" => gettext("Create a Certificate Signing Request"),
38
	"sign" => gettext("Sign a Certificate Signing Request")
39
);
40

    
41
$cert_keylens = array("1024", "2048", "3072", "4096", "6144", "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
	init_config_arr(array('system', 'user'));
56
	$a_user =& $config['system']['user'];
57
}
58

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

    
63
init_config_arr(array('ca'));
64
$a_ca = &$config['ca'];
65

    
66
init_config_arr(array('cert'));
67
$a_cert = &$config['cert'];
68

    
69
$internal_ca_count = 0;
70
foreach ($a_ca as $ca) {
71
	if ($ca['prv']) {
72
		$internal_ca_count++;
73
	}
74
}
75

    
76
$act = $_REQUEST['act'];
77

    
78
if ($_POST['act'] == "del") {
79

    
80
	if (!isset($a_cert[$id])) {
81
		pfSenseHeader("system_certmanager.php");
82
		exit;
83
	}
84

    
85
	unset($a_cert[$id]);
86
	write_config();
87
	$savemsg = sprintf(gettext("Certificate %s successfully deleted."), htmlspecialchars($a_cert[$id]['descr']));
88
	pfSenseHeader("system_certmanager.php");
89
	exit;
90
}
91

    
92
if ($act == "new") {
93
	$pconfig['method'] = $_POST['method'];
94
	$pconfig['keylen'] = "2048";
95
	$pconfig['digest_alg'] = "sha256";
96
	$pconfig['csr_keylen'] = "2048";
97
	$pconfig['csr_digest_alg'] = "sha256";
98
	$pconfig['csrsign_digest_alg'] = "sha256";
99
	$pconfig['type'] = "user";
100
	$pconfig['lifetime'] = "3650";
101
}
102

    
103
if ($act == "exp") {
104

    
105
	if (!$a_cert[$id]) {
106
		pfSenseHeader("system_certmanager.php");
107
		exit;
108
	}
109

    
110
	$exp_name = urlencode("{$a_cert[$id]['descr']}.crt");
111
	$exp_data = base64_decode($a_cert[$id]['crt']);
112
	$exp_size = strlen($exp_data);
113

    
114
	header("Content-Type: application/octet-stream");
115
	header("Content-Disposition: attachment; filename={$exp_name}");
116
	header("Content-Length: $exp_size");
117
	echo $exp_data;
118
	exit;
119
}
120

    
121
if ($act == "req") {
122

    
123
	if (!$a_cert[$id]) {
124
		pfSenseHeader("system_certmanager.php");
125
		exit;
126
	}
127

    
128
	$exp_name = urlencode("{$a_cert[$id]['descr']}.req");
129
	$exp_data = base64_decode($a_cert[$id]['csr']);
130
	$exp_size = strlen($exp_data);
131

    
132
	header("Content-Type: application/octet-stream");
133
	header("Content-Disposition: attachment; filename={$exp_name}");
134
	header("Content-Length: $exp_size");
135
	echo $exp_data;
136
	exit;
137
}
138

    
139
if ($act == "key") {
140

    
141
	if (!$a_cert[$id]) {
142
		pfSenseHeader("system_certmanager.php");
143
		exit;
144
	}
145

    
146
	$exp_name = urlencode("{$a_cert[$id]['descr']}.key");
147
	$exp_data = base64_decode($a_cert[$id]['prv']);
148
	$exp_size = strlen($exp_data);
149

    
150
	header("Content-Type: application/octet-stream");
151
	header("Content-Disposition: attachment; filename={$exp_name}");
152
	header("Content-Length: $exp_size");
153
	echo $exp_data;
154
	exit;
155
}
156

    
157
if ($act == "p12") {
158
	if (!$a_cert[$id]) {
159
		pfSenseHeader("system_certmanager.php");
160
		exit;
161
	}
162

    
163
	$exp_name = urlencode("{$a_cert[$id]['descr']}.p12");
164
	$args = array();
165
	$args['friendly_name'] = $a_cert[$id]['descr'];
166

    
167
	$ca = lookup_ca($a_cert[$id]['caref']);
168

    
169
	if ($ca) {
170
		$args['extracerts'] = openssl_x509_read(base64_decode($ca['crt']));
171
	}
172

    
173
	$res_crt = openssl_x509_read(base64_decode($a_cert[$id]['crt']));
174
	$res_key = openssl_pkey_get_private(array(0 => base64_decode($a_cert[$id]['prv']) , 1 => ""));
175

    
176
	$exp_data = "";
177
	openssl_pkcs12_export($res_crt, $exp_data, $res_key, null, $args);
178
	$exp_size = strlen($exp_data);
179

    
180
	header("Content-Type: application/octet-stream");
181
	header("Content-Disposition: attachment; filename={$exp_name}");
182
	header("Content-Length: $exp_size");
183
	echo $exp_data;
184
	exit;
185
}
186

    
187
if ($act == "csr") {
188
	if (!$a_cert[$id]) {
189
		pfSenseHeader("system_certmanager.php");
190
		exit;
191
	}
192

    
193
	$pconfig['descr'] = $a_cert[$id]['descr'];
194
	$pconfig['csr'] = base64_decode($a_cert[$id]['csr']);
195
}
196

    
197
if ($_POST['save']) {
198

    
199
	if ($_POST['save'] == gettext("Save")) {
200
		$input_errors = array();
201
		$pconfig = $_POST;
202

    
203
		/* input validation */
204
		if ($pconfig['method'] == "sign") {
205
			$reqdfields = explode(" ",
206
				"descr catosignwith");
207
			$reqdfieldsn = array(
208
				gettext("Descriptive name"),
209
				gettext("CA to sign with"));
210

    
211
			if (($_POST['csrtosign'] === "new") &&
212
			    ((!strstr($_POST['csrpaste'], "BEGIN CERTIFICATE REQUEST") || !strstr($_POST['csrpaste'], "END CERTIFICATE REQUEST")) &&
213
			    (!strstr($_POST['csrpaste'], "BEGIN NEW CERTIFICATE REQUEST") || !strstr($_POST['csrpaste'], "END NEW CERTIFICATE REQUEST")))) {
214
				$input_errors[] = gettext("This signing request does not appear to be valid.");
215
			}
216

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

    
222
		}
223

    
224
		if ($pconfig['method'] == "import") {
225
			$reqdfields = explode(" ",
226
				"descr cert key");
227
			$reqdfieldsn = array(
228
				gettext("Descriptive name"),
229
				gettext("Certificate data"),
230
				gettext("Key data"));
231
			if ($_POST['cert'] && (!strstr($_POST['cert'], "BEGIN CERTIFICATE") || !strstr($_POST['cert'], "END CERTIFICATE"))) {
232
				$input_errors[] = gettext("This certificate does not appear to be valid.");
233
			}
234

    
235
			if (cert_get_publickey($_POST['cert'], false) != cert_get_publickey($_POST['key'], false, 'prv')) {
236
				$input_errors[] = gettext("The submitted private key does not match the submitted certificate data.");
237
			}
238
		}
239

    
240
		if ($pconfig['method'] == "internal") {
241
			$reqdfields = explode(" ",
242
				"descr caref keylen type lifetime dn_commonname");
243
			$reqdfieldsn = array(
244
				gettext("Descriptive name"),
245
				gettext("Certificate authority"),
246
				gettext("Key length"),
247
				gettext("Certificate Type"),
248
				gettext("Lifetime"),
249
				gettext("Distinguished name Common Name"));
250
		}
251

    
252
		if ($pconfig['method'] == "external") {
253
			$reqdfields = explode(" ",
254
				"descr csr_keylen csr_dn_commonname");
255
			$reqdfieldsn = array(
256
				gettext("Descriptive name"),
257
				gettext("Key length"),
258
				gettext("Distinguished name Common Name"));
259
		}
260

    
261
		if ($pconfig['method'] == "existing") {
262
			$reqdfields = array("certref");
263
			$reqdfieldsn = array(gettext("Existing Certificate Choice"));
264
		}
265

    
266
		$altnames = array();
267
		do_input_validation($_POST, $reqdfields, $reqdfieldsn, $input_errors);
268

    
269
		if ($pconfig['method'] != "import" && $pconfig['method'] != "existing") {
270
			/* subjectAltNames */
271
			$san_typevar = 'altname_type';
272
			$san_valuevar = 'altname_value';
273
			// This is just the blank alternate name that is added for display purposes. We don't want to validate/save it
274
			if ($_POST["{$san_valuevar}0"] == "") {
275
				unset($_POST["{$san_typevar}0"]);
276
				unset($_POST["{$san_valuevar}0"]);
277
			}
278
			foreach ($_POST as $key => $value) {
279
				$entry = '';
280
				if (!substr_compare($san_typevar, $key, 0, strlen($san_typevar))) {
281
					$entry = substr($key, strlen($san_typevar));
282
					$field = 'type';
283
				} elseif (!substr_compare($san_valuevar, $key, 0, strlen($san_valuevar))) {
284
					$entry = substr($key, strlen($san_valuevar));
285
					$field = 'value';
286
				}
287

    
288
				if (ctype_digit($entry)) {
289
					$entry++;	// Pre-bootstrap code is one-indexed, but the bootstrap code is 0-indexed
290
					$altnames[$entry][$field] = $value;
291
				}
292
			}
293

    
294
			$pconfig['altnames']['item'] = $altnames;
295

    
296
			/* Input validation for subjectAltNames */
297
			foreach ($altnames as $idx => $altname) {
298
				switch ($altname['type']) {
299
					case "DNS":
300
						if (!is_hostname($altname['value'], true) || is_ipaddr($altname['value'])) {
301
							array_push($input_errors, "DNS subjectAltName values must be valid hostnames, FQDNs or wildcard domains.");
302
						}
303
						break;
304
					case "IP":
305
						if (!is_ipaddr($altname['value'])) {
306
							array_push($input_errors, "IP subjectAltName values must be valid IP Addresses");
307
						}
308
						break;
309
					case "email":
310
						if (empty($altname['value'])) {
311
							array_push($input_errors, "An e-mail address must be provided for this type of subjectAltName");
312
						}
313
						if (preg_match("/[\!\#\$\%\^\(\)\~\?\>\<\&\/\\\,\"\']/", $altname['value'])) {
314
							array_push($input_errors, "The e-mail provided in a subjectAltName contains invalid characters.");
315
						}
316
						break;
317
					case "URI":
318
						/* Close enough? */
319
						if (!is_URL($altname['value'])) {
320
							$input_errors[] = "URI subjectAltName types must be a valid URI";
321
						}
322
						break;
323
					default:
324
						$input_errors[] = "Unrecognized subjectAltName type.";
325
				}
326
			}
327

    
328
			/* Make sure we do not have invalid characters in the fields for the certificate */
329

    
330
			if (preg_match("/[\?\>\<\&\/\\\"\']/", $_POST['descr'])) {
331
				array_push($input_errors, "The field 'Descriptive Name' contains invalid characters.");
332
			}
333

    
334
			switch ($pconfig['method']) {
335
				case "internal":
336
					if (isset($_POST["keylen"]) && !in_array($_POST["keylen"], $cert_keylens)) {
337
						array_push($input_errors, gettext("Please select a valid Key Length."));
338
					}
339
					if (!in_array($_POST["digest_alg"], $openssl_digest_algs)) {
340
						array_push($input_errors, gettext("Please select a valid Digest Algorithm."));
341
					}
342
					break;
343
				case "external":
344
					if (isset($_POST["csr_keylen"]) && !in_array($_POST["csr_keylen"], $cert_keylens)) {
345
						array_push($input_errors, gettext("Please select a valid Key Length."));
346
					}
347
					if (!in_array($_POST["csr_digest_alg"], $openssl_digest_algs)) {
348
						array_push($input_errors, gettext("Please select a valid Digest Algorithm."));
349
					}
350
					break;
351
				case "sign":
352
					if (!in_array($_POST["csrsign_digest_alg"], $openssl_digest_algs)) {
353
						array_push($input_errors, gettext("Please select a valid Digest Algorithm."));
354
					}
355
					break;
356
				default:
357
					break;
358
			}
359
		}
360

    
361
		/* save modifications */
362
		if (!$input_errors) {
363

    
364
			if ($pconfig['method'] == "existing") {
365
				$cert = lookup_cert($pconfig['certref']);
366
				if ($cert && $a_user) {
367
					$a_user[$userid]['cert'][] = $cert['refid'];
368
				}
369
			} else if ($pconfig['method'] == "sign") { // Sign a CSR
370
				$csrid = lookup_cert($pconfig['csrtosign']);
371
				$ca = & lookup_ca($pconfig['catosignwith']);
372

    
373
				// Read the CSR from $config, or if a new one, from the textarea
374
				if ($pconfig['csrtosign'] === "new") {
375
					$csr = $pconfig['csrpaste'];
376
				} else {
377
					$csr = base64_decode($csrid['csr']);
378
				}
379
				if (count($altnames)) {
380
					foreach ($altnames as $altname) {
381
						$altnames_tmp[] = "{$altname['type']}:" . cert_escape_x509_chars($altname['value']);
382
					}
383
					$altname_str = implode(",", $altnames_tmp);
384
				}
385

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

    
388
				if ($n509) {
389
					// Gather the details required to save the new cert
390
					$newcert = array();
391
					$newcert['refid'] = uniqid();
392
					$newcert['caref'] = $pconfig['catosignwith'];
393
					$newcert['descr'] = $pconfig['descr'];
394
					$newcert['type'] = $pconfig['type'];
395
					$newcert['crt'] = base64_encode($n509);
396

    
397
					if ($pconfig['csrtosign'] === "new") {
398
						$newcert['prv'] = base64_encode($pconfig['keypaste']);
399
					} else {
400
						$newcert['prv'] = $csrid['prv'];
401
					}
402

    
403
					// Add it to the config file
404
					$config['cert'][] = $newcert;
405
				}
406

    
407
			} else {
408
				$cert = array();
409
				$cert['refid'] = uniqid();
410
				if (isset($id) && $a_cert[$id]) {
411
					$cert = $a_cert[$id];
412
				}
413

    
414
				$cert['descr'] = $pconfig['descr'];
415

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

    
418
				if ($pconfig['method'] == "import") {
419
					cert_import($cert, $pconfig['cert'], $pconfig['key']);
420
				}
421

    
422
				if ($pconfig['method'] == "internal") {
423
					$dn = array('commonName' => cert_escape_x509_chars($pconfig['dn_commonname']));
424
					if (!empty($pconfig['dn_country'])) {
425
						$dn['countryName'] = $pconfig['dn_country'];
426
					}
427
					if (!empty($pconfig['dn_state'])) {
428
						$dn['stateOrProvinceName'] = cert_escape_x509_chars($pconfig['dn_state']);
429
					}
430
					if (!empty($pconfig['dn_city'])) {
431
						$dn['localityName'] = cert_escape_x509_chars($pconfig['dn_city']);
432
					}
433
					if (!empty($pconfig['dn_organization'])) {
434
						$dn['organizationName'] = cert_escape_x509_chars($pconfig['dn_organization']);
435
					}
436
					if (!empty($pconfig['dn_organizationalunit'])) {
437
						$dn['organizationalUnitName'] = cert_escape_x509_chars($pconfig['dn_organizationalunit']);
438
					}
439

    
440
					$altnames_tmp = array();
441
					$cn_altname = cert_add_altname_type($pconfig['dn_commonname']);
442
					if (!empty($cn_altname)) {
443
						$altnames_tmp[] = $cn_altname;
444
					}
445
					if (count($altnames)) {
446
						foreach ($altnames as $altname) {
447
							// The CN is added as a SAN automatically, do not add it again.
448
							if ($altname['value'] != $pconfig['dn_commonname']) {
449
								$altnames_tmp[] = "{$altname['type']}:" . cert_escape_x509_chars($altname['value']);
450
							}
451
						}
452
					}
453
					if (!empty($altnames_tmp)) {
454
						$dn['subjectAltName'] = implode(",", $altnames_tmp);
455
					}
456

    
457
					if (!cert_create($cert, $pconfig['caref'], $pconfig['keylen'], $pconfig['lifetime'], $dn, $pconfig['type'], $pconfig['digest_alg'])) {
458
						$input_errors = array();
459
						while ($ssl_err = openssl_error_string()) {
460
							if (strpos($ssl_err, 'NCONF_get_string:no value') === false) {
461
								array_push($input_errors, "openssl library returns: " . $ssl_err);
462
							}
463
						}
464
					}
465
				}
466

    
467
				if ($pconfig['method'] == "external") {
468
					$dn = array('commonName' => cert_escape_x509_chars($pconfig['csr_dn_commonname']));
469
					if (!empty($pconfig['csr_dn_country'])) {
470
						$dn['countryName'] = $pconfig['csr_dn_country'];
471
					}
472
					if (!empty($pconfig['csr_dn_state'])) {
473
						$dn['stateOrProvinceName'] = cert_escape_x509_chars($pconfig['csr_dn_state']);
474
					}
475
					if (!empty($pconfig['csr_dn_city'])) {
476
						$dn['localityName'] = cert_escape_x509_chars($pconfig['csr_dn_city']);
477
					}
478
					if (!empty($pconfig['csr_dn_organization'])) {
479
						$dn['organizationName'] = cert_escape_x509_chars($pconfig['csr_dn_organization']);
480
					}
481
					if (!empty($pconfig['csr_dn_organizationalunit'])) {
482
						$dn['organizationalUnitName'] = cert_escape_x509_chars($pconfig['csr_dn_organizationalunit']);
483
					}
484

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

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

    
512
				error_reporting($old_err_level);
513

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

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

    
525
			if (!$input_errors) {
526
				write_config();
527
			}
528

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

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

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

    
546
		do_input_validation($_POST, $reqdfields, $reqdfieldsn, $input_errors);
547

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

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

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

    
572
		/* save modifications */
573
		if (!$input_errors) {
574

    
575
			$cert = $a_cert[$id];
576

    
577
			$cert['descr'] = $pconfig['descr'];
578

    
579
			csr_complete($cert, $pconfig['cert']);
580

    
581
			$a_cert[$id] = $cert;
582

    
583
			write_config();
584

    
585
			pfSenseHeader("system_certmanager.php");
586
		}
587
	}
588
}
589

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

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

    
599
if ($input_errors) {
600
	print_input_errors($input_errors);
601
}
602

    
603
if ($savemsg) {
604
	print_info_box($savemsg, 'success');
605
}
606

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

    
613
if ($act == "new" || (($_POST['save'] == gettext("Save")) && $input_errors)) {
614
	$form = new Form();
615
	$form->setAction('system_certmanager.php?act=edit');
616

    
617
	if (isset($userid) && $a_user) {
618
		$form->addGlobal(new Form_Input(
619
			'userid',
620
			null,
621
			'hidden',
622
			$userid
623
		));
624
	}
625

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

    
635
	$section = new Form_Section('Add/Sign a New Certificate');
636

    
637
	if (!isset($id)) {
638
		$section->addInput(new Form_Select(
639
			'method',
640
			'*Method',
641
			$pconfig['method'],
642
			$cert_methods
643
		))->toggles();
644
	}
645

    
646
	$section->addInput(new Form_Input(
647
		'descr',
648
		'*Descriptive name',
649
		'text',
650
		($a_user && empty($pconfig['descr'])) ? $a_user[$userid]['name'] : $pconfig['descr']
651
	))->addClass('toggle-existing');
652

    
653
	$form->add($section);
654

    
655
	// Return an array containing the IDs od all CAs
656
	function list_cas() {
657
		global $a_ca;
658
		$allCas = array();
659

    
660
		foreach ($a_ca as $ca) {
661
			if ($ca['prv']) {
662
				$allCas[$ca['refid']] = $ca['descr'];
663
			}
664
		}
665

    
666
		return $allCas;
667
	}
668

    
669
	// Return an array containing the IDs od all CSRs
670
	function list_csrs() {
671
		global $config;
672
		$allCsrs = array();
673

    
674
		foreach ($config['cert'] as $cert) {
675
			if ($cert['csr']) {
676
				$allCsrs[$cert['refid']] = $cert['descr'];
677
			}
678
		}
679

    
680
		return ['new' => gettext('New CSR (Paste below)')] + $allCsrs;
681
	}
682

    
683
	$section = new Form_Section('Sign CSR');
684
	$section->addClass('toggle-sign collapse');
685

    
686
	$section->AddInput(new Form_Select(
687
		'catosignwith',
688
		'*CA to sign with',
689
		$pconfig['catosignwith'],
690
		list_cas()
691
	));
692

    
693
	$section->AddInput(new Form_Select(
694
		'csrtosign',
695
		'*CSR to sign',
696
		isset($pconfig['csrtosign']) ? $pconfig['csrtosign'] : 'new',
697
		list_csrs()
698
	));
699

    
700
	$section->addInput(new Form_Textarea(
701
		'csrpaste',
702
		'CSR data',
703
		$pconfig['csrpaste']
704
	))->setHelp('Paste a Certificate Signing Request in X.509 PEM format here.');
705

    
706
	$section->addInput(new Form_Textarea(
707
		'keypaste',
708
		'Key data',
709
		$pconfig['keypaste']
710
	))->setHelp('Optionally paste a private key here. The key will be associated with the newly signed certificate in pfSense');
711

    
712
	$section->addInput(new Form_Input(
713
		'csrsign_lifetime',
714
		'*Certificate Lifetime (days)',
715
		'number',
716
		$pconfig['csrsign_lifetime'] ? $pconfig['csrsign_lifetime']:'3650'
717
	));
718
	$section->addInput(new Form_Select(
719
		'csrsign_digest_alg',
720
		'*Digest Algorithm',
721
		$pconfig['csrsign_digest_alg'],
722
		array_combine($openssl_digest_algs, $openssl_digest_algs)
723
	))->setHelp('NOTE: It is recommended to use an algorithm stronger than '.
724
		'SHA1 when possible');
725

    
726
	$form->add($section);
727

    
728
	$section = new Form_Section('Import Certificate');
729
	$section->addClass('toggle-import collapse');
730

    
731
	$section->addInput(new Form_Textarea(
732
		'cert',
733
		'*Certificate data',
734
		$pconfig['cert']
735
	))->setHelp('Paste a certificate in X.509 PEM format here.');
736

    
737
	$section->addInput(new Form_Textarea(
738
		'key',
739
		'*Private key data',
740
		$pconfig['key']
741
	))->setHelp('Paste a private key in X.509 PEM format here.');
742

    
743
	$form->add($section);
744
	$section = new Form_Section('Internal Certificate');
745
	$section->addClass('toggle-internal collapse');
746

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

    
761
			$allCas[ $ca['refid'] ] = $ca['descr'];
762
		}
763

    
764
		$section->addInput(new Form_Select(
765
			'caref',
766
			'*Certificate authority',
767
			$pconfig['caref'],
768
			$allCas
769
		));
770
	}
771

    
772
	$section->addInput(new Form_Select(
773
		'keylen',
774
		'*Key length',
775
		$pconfig['keylen'],
776
		array_combine($cert_keylens, $cert_keylens)
777
	));
778

    
779
	$section->addInput(new Form_Select(
780
		'digest_alg',
781
		'*Digest Algorithm',
782
		$pconfig['digest_alg'],
783
		array_combine($openssl_digest_algs, $openssl_digest_algs)
784
	))->setHelp('NOTE: It is recommended to use an algorithm stronger than '.
785
		'SHA1 when possible.');
786

    
787
	$section->addInput(new Form_Input(
788
		'lifetime',
789
		'*Lifetime (days)',
790
		'number',
791
		$pconfig['lifetime']
792
	));
793

    
794
	$section->addInput(new Form_Input(
795
		'dn_commonname',
796
		'*Common Name',
797
		'text',
798
		$pconfig['dn_commonname'],
799
		['placeholder' => 'e.g. www.example.com']
800
	));
801

    
802
	$section->addInput(new Form_StaticText(
803
		null,
804
		gettext('The following certificate subject components are optional and may be left blank.')
805
	));
806

    
807
	$section->addInput(new Form_Select(
808
		'dn_country',
809
		'Country Code',
810
		$pconfig['dn_country'],
811
		get_cert_country_codes()
812
	));
813

    
814
	$section->addInput(new Form_Input(
815
		'dn_state',
816
		'State or Province',
817
		'text',
818
		$pconfig['dn_state'],
819
		['placeholder' => 'e.g. Texas']
820
	));
821

    
822
	$section->addInput(new Form_Input(
823
		'dn_city',
824
		'City',
825
		'text',
826
		$pconfig['dn_city'],
827
		['placeholder' => 'e.g. Austin']
828
	));
829

    
830
	$section->addInput(new Form_Input(
831
		'dn_organization',
832
		'Organization',
833
		'text',
834
		$pconfig['dn_organization'],
835
		['placeholder' => 'e.g. My Company Inc']
836
	));
837

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

    
846
	$form->add($section);
847
	$section = new Form_Section('External Signing Request');
848
	$section->addClass('toggle-external collapse');
849

    
850
	$section->addInput(new Form_Select(
851
		'csr_keylen',
852
		'*Key length',
853
		$pconfig['csr_keylen'],
854
		array_combine($cert_keylens, $cert_keylens)
855
	));
856

    
857
	$section->addInput(new Form_Select(
858
		'csr_digest_alg',
859
		'*Digest Algorithm',
860
		$pconfig['csr_digest_alg'],
861
		array_combine($openssl_digest_algs, $openssl_digest_algs)
862
	))->setHelp('NOTE: It is recommended to use an algorithm stronger than '.
863
		'SHA1 when possible');
864

    
865
	$section->addInput(new Form_Input(
866
		'csr_dn_commonname',
867
		'*Common Name',
868
		'text',
869
		$pconfig['csr_dn_commonname'],
870
		['placeholder' => 'e.g. internal-ca']
871
	));
872

    
873
	$section->addInput(new Form_StaticText(
874
		null,
875
		gettext('The following certificate subject components are optional and may be left blank.')
876
	));
877

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

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

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

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

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

    
917
	$form->add($section);
918
	$section = new Form_Section('Choose an Existing Certificate');
919
	$section->addClass('toggle-existing collapse');
920

    
921
	$existCerts = array();
922

    
923
	foreach ($config['cert'] as $cert) {
924
		if (!is_array($cert) || empty($cert)) {
925
			continue;
926
		}
927
		if (is_array($config['system']['user'][$userid]['cert'])) { // Could be MIA!
928
			if (isset($userid) && in_array($cert['refid'], $config['system']['user'][$userid]['cert'])) {
929
				continue;
930
			}
931
		}
932

    
933
		$ca = lookup_ca($cert['caref']);
934
		if ($ca) {
935
			$cert['descr'] .= " (CA: {$ca['descr']})";
936
		}
937

    
938
		if (cert_in_use($cert['refid'])) {
939
			$cert['descr'] .= " (In Use)";
940
		}
941
		if (is_cert_revoked($cert)) {
942
			$cert['descr'] .= " (Revoked)";
943
		}
944

    
945
		$existCerts[ $cert['refid'] ] = $cert['descr'];
946
	}
947

    
948
	$section->addInput(new Form_Select(
949
		'certref',
950
		'*Existing Certificates',
951
		$pconfig['certref'],
952
		$existCerts
953
	));
954

    
955
	$form->add($section);
956

    
957
	$section = new Form_Section('Certificate Attributes');
958
	$section->addClass('toggle-external toggle-internal toggle-sign collapse');
959

    
960
	$section->addInput(new Form_StaticText(
961
		gettext('Attribute Notes'),
962
		'<span class="help-block">'.
963
		gettext('The following attributes are added to certificates and ' .
964
		'requests when they are created or signed. These attributes behave ' .
965
		'differently depending on the selected mode.') .
966
		'<br/><br/>' .
967
		'<span class="toggle-internal collapse">' . gettext('For Internal Certificates, these attributes are added directly to the certificate as shown.') . '</span>' .
968
		'<span class="toggle-external collapse">' .
969
		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. ') .
970
		'<br/><br/>' .
971
		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>' .
972
		'<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>' .
973
		'</span>'
974
	));
975

    
976
	$section->addInput(new Form_Select(
977
		'type',
978
		'*Certificate Type',
979
		$pconfig['type'],
980
		$cert_types
981
	))->setHelp('Add type-specific usage attributes to the signed certificate.' .
982
		' Used for placing usage restrictions on, or granting abilities to, ' .
983
		'the signed certificate.');
984

    
985
	if (empty($pconfig['altnames']['item'])) {
986
		$pconfig['altnames']['item'] = array(
987
			array('type' => null, 'value' => null)
988
		);
989
	}
990

    
991
	$counter = 0;
992
	$numrows = count($pconfig['altnames']['item']) - 1;
993

    
994
	foreach ($pconfig['altnames']['item'] as $item) {
995

    
996
		$group = new Form_Group($counter == 0 ? 'Alternative Names':'');
997

    
998
		$group->add(new Form_Select(
999
			'altname_type' . $counter,
1000
			'Type',
1001
			$item['type'],
1002
			$cert_altname_types
1003
		))->setHelp(($counter == $numrows) ? 'Type':null);
1004

    
1005
		$group->add(new Form_Input(
1006
			'altname_value' . $counter,
1007
			null,
1008
			'text',
1009
			$item['value']
1010
		))->setHelp(($counter == $numrows) ? 'Value':null);
1011

    
1012
		$group->add(new Form_Button(
1013
			'deleterow' . $counter,
1014
			'Delete',
1015
			null,
1016
			'fa-trash'
1017
		))->addClass('btn-warning');
1018

    
1019
		$group->addClass('repeatable');
1020

    
1021
		$group->setHelp('Enter additional identifiers for the certificate ' .
1022
			'in this list. The Common Name field is automatically ' .
1023
			'added to the certificate as an Alternative Name. ' .
1024
			'The signing CA may ignore or change these values.');
1025

    
1026
		$section->add($group);
1027

    
1028
		$counter++;
1029
	}
1030

    
1031
	$section->addInput(new Form_Button(
1032
		'addrow',
1033
		'Add',
1034
		null,
1035
		'fa-plus'
1036
	))->addClass('btn-success');
1037

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

    
1040

    
1041
	print $form;
1042

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

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

    
1049
	$section->addInput(new Form_Input(
1050
		'descr',
1051
		'*Descriptive name',
1052
		'text',
1053
		$pconfig['descr']
1054
	));
1055

    
1056
	$section->addInput(new Form_Textarea(
1057
		'csr',
1058
		'Signing request data',
1059
		$pconfig['csr']
1060
	))->setReadonly()
1061
	  ->setWidth(7)
1062
	  ->setHelp('Copy the certificate signing data from here and forward it to a certificate authority for signing.');
1063

    
1064
	$section->addInput(new Form_Textarea(
1065
		'cert',
1066
		'*Final certificate data',
1067
		$pconfig['cert']
1068
	))->setWidth(7)
1069
	  ->setHelp('Paste the certificate received from the certificate authority here.');
1070

    
1071
	 if (isset($id) && $a_cert[$id]) {
1072
		 $section->addInput(new Form_Input(
1073
			'id',
1074
			null,
1075
			'hidden',
1076
			$id
1077
		 ));
1078

    
1079
		 $section->addInput(new Form_Input(
1080
			'act',
1081
			null,
1082
			'hidden',
1083
			'csr'
1084
		 ));
1085
	 }
1086

    
1087
	$form->add($section);
1088

    
1089
	$form->addGlobal(new Form_Button(
1090
		'save',
1091
		'Update',
1092
		null,
1093
		'fa-save'
1094
	))->addClass('btn-primary');
1095

    
1096
	print($form);
1097
} else {
1098
?>
1099
<div class="panel panel-default">
1100
	<div class="panel-heading"><h2 class="panel-title"><?=gettext('Certificates')?></h2></div>
1101
	<div class="panel-body">
1102
		<div class="table-responsive">
1103
		<table class="table table-striped table-hover">
1104
			<thead>
1105
				<tr>
1106
					<th><?=gettext("Name")?></th>
1107
					<th><?=gettext("Issuer")?></th>
1108
					<th><?=gettext("Distinguished Name")?></th>
1109
					<th><?=gettext("In Use")?></th>
1110

    
1111
					<th class="col-sm-2"><?=gettext("Actions")?></th>
1112
				</tr>
1113
			</thead>
1114
			<tbody>
1115
<?php
1116

    
1117
$pluginparams = array();
1118
$pluginparams['type'] = 'certificates';
1119
$pluginparams['event'] = 'used_certificates';
1120
$certificates_used_by_packages = pkg_call_plugins('plugin_certificates', $pluginparams);
1121
$i = 0;
1122
foreach ($a_cert as $i => $cert):
1123
	if (!is_array($cert) || empty($cert)) {
1124
		continue;
1125
	}
1126
	$name = htmlspecialchars($cert['descr']);
1127
	$sans = array();
1128
	if ($cert['crt']) {
1129
		$subj = cert_get_subject($cert['crt']);
1130
		$issuer = cert_get_issuer($cert['crt']);
1131
		$purpose = cert_get_purpose($cert['crt']);
1132
		$sans = cert_get_sans($cert['crt']);
1133
		list($startdate, $enddate) = cert_get_dates($cert['crt']);
1134

    
1135
		if ($subj == $issuer) {
1136
			$caname = '<i>'. gettext("self-signed") .'</i>';
1137
		} else {
1138
			$caname = '<i>'. gettext("external").'</i>';
1139
		}
1140

    
1141
		$subj = htmlspecialchars(cert_escape_x509_chars($subj, true));
1142
	} else {
1143
		$subj = "";
1144
		$issuer = "";
1145
		$purpose = "";
1146
		$startdate = "";
1147
		$enddate = "";
1148
		$caname = "<em>" . gettext("private key only") . "</em>";
1149
	}
1150

    
1151
	if ($cert['csr']) {
1152
		$subj = htmlspecialchars(cert_escape_x509_chars(csr_get_subject($cert['csr']), true));
1153
		$sans = cert_get_sans($cert['crt']);
1154
		$caname = "<em>" . gettext("external - signature pending") . "</em>";
1155
	}
1156

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

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

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

    
1284

    
1285
?>
1286
<script type="text/javascript">
1287
//<![CDATA[
1288
events.push(function() {
1289

    
1290
<?php if ($internal_ca_count): ?>
1291
	function internalca_change() {
1292

    
1293
		caref = $('#caref').val();
1294

    
1295
		switch (caref) {
1296
<?php
1297
			foreach ($a_ca as $ca):
1298
				if (!$ca['prv']) {
1299
					continue;
1300
				}
1301

    
1302
				$subject = cert_get_subject_hash($ca['crt']);
1303
?>
1304
				case "<?=$ca['refid'];?>":
1305
					$('#dn_country').val(<?=json_encode(cert_escape_x509_chars($subject['C'], true));?>);
1306
					$('#dn_state').val(<?=json_encode(cert_escape_x509_chars($subject['ST'], true));?>);
1307
					$('#dn_city').val(<?=json_encode(cert_escape_x509_chars($subject['L'], true));?>);
1308
					$('#dn_organization').val(<?=json_encode(cert_escape_x509_chars($subject['O'], true));?>);
1309
					$('#dn_organizationalunit').val(<?=json_encode(cert_escape_x509_chars($subject['OU'], true));?>);
1310
					break;
1311
<?php
1312
			endforeach;
1313
?>
1314
		}
1315
	}
1316

    
1317
	function set_csr_ro() {
1318
		var newcsr = ($('#csrtosign').val() == "new");
1319

    
1320
		$('#csrpaste').attr('readonly', !newcsr);
1321
		$('#keypaste').attr('readonly', !newcsr);
1322
		setRequired('csrpaste', newcsr);
1323
	}
1324

    
1325
	// ---------- Click checkbox handlers ---------------------------------------------------------
1326

    
1327
	$('#caref').on('change', function() {
1328
		internalca_change();
1329
	});
1330

    
1331
	$('#csrtosign').change(function () {
1332
		set_csr_ro();
1333
	});
1334

    
1335
	// ---------- On initial page load ------------------------------------------------------------
1336

    
1337
	internalca_change();
1338
	set_csr_ro();
1339

    
1340
	// Suppress "Delete row" button if there are fewer than two rows
1341
	checkLastRow();
1342

    
1343
<?php endif; ?>
1344

    
1345

    
1346
});
1347
//]]>
1348
</script>
1349
<?php
1350
include('foot.inc');
(201-201/234)