Project

General

Profile

Download (38.7 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-2018 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
// Load valid country codes
614
$dn_cc = array();
615
if (file_exists("/etc/ca_countries")) {
616
	$dn_cc_file=file("/etc/ca_countries");
617
	$dn_cc[''] = gettext("None");
618
	foreach ($dn_cc_file as $line) {
619
		if (preg_match('/^(\S*)\s(.*)$/', $line, $matches)) {
620
			$dn_cc[$matches[1]] = $matches[1];
621
		}
622
	}
623
}
624

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

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

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

    
647
	$section = new Form_Section('Add/Sign a New Certificate');
648

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

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

    
665
	$form->add($section);
666

    
667
	// Return an array containing the IDs od all CAs
668
	function list_cas() {
669
		global $a_ca;
670
		$allCas = array();
671

    
672
		foreach ($a_ca as $ca) {
673
			if ($ca['prv']) {
674
				$allCas[$ca['refid']] = $ca['descr'];
675
			}
676
		}
677

    
678
		return $allCas;
679
	}
680

    
681
	// Return an array containing the IDs od all CSRs
682
	function list_csrs() {
683
		global $config;
684
		$allCsrs = array();
685

    
686
		foreach ($config['cert'] as $cert) {
687
			if ($cert['csr']) {
688
				$allCsrs[$cert['refid']] = $cert['descr'];
689
			}
690
		}
691

    
692
		return ['new' => gettext('New CSR (Paste below)')] + $allCsrs;
693
	}
694

    
695
	$section = new Form_Section('Sign CSR');
696
	$section->addClass('toggle-sign collapse');
697

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

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

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

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

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

    
738
	$form->add($section);
739

    
740
	$section = new Form_Section('Import Certificate');
741
	$section->addClass('toggle-import collapse');
742

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

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

    
755
	$form->add($section);
756
	$section = new Form_Section('Internal Certificate');
757
	$section->addClass('toggle-internal collapse');
758

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

    
773
			$allCas[ $ca['refid'] ] = $ca['descr'];
774
		}
775

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

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

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

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

    
806
	$section->addInput(new Form_Input(
807
		'dn_commonname',
808
		'*Common Name',
809
		'text',
810
		$pconfig['dn_commonname'],
811
		['placeholder' => 'e.g. www.example.com']
812
	));
813

    
814
	$section->addInput(new Form_StaticText(
815
		null,
816
		gettext('The following certificate subject components are optional and may be left blank.')
817
	));
818

    
819
	$section->addInput(new Form_Select(
820
		'dn_country',
821
		'Country Code',
822
		$pconfig['dn_country'],
823
		$dn_cc
824
	));
825

    
826
	$section->addInput(new Form_Input(
827
		'dn_state',
828
		'State or Province',
829
		'text',
830
		$pconfig['dn_state'],
831
		['placeholder' => 'e.g. Texas']
832
	));
833

    
834
	$section->addInput(new Form_Input(
835
		'dn_city',
836
		'City',
837
		'text',
838
		$pconfig['dn_city'],
839
		['placeholder' => 'e.g. Austin']
840
	));
841

    
842
	$section->addInput(new Form_Input(
843
		'dn_organization',
844
		'Organization',
845
		'text',
846
		$pconfig['dn_organization'],
847
		['placeholder' => 'e.g. My Company Inc']
848
	));
849

    
850
	$section->addInput(new Form_Input(
851
		'dn_organizationalunit',
852
		'Organizational Unit',
853
		'text',
854
		$pconfig['dn_organizationalunit'],
855
		['placeholder' => 'e.g. My Department Name (optional)']
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_Input(
878
		'csr_dn_commonname',
879
		'*Common Name',
880
		'text',
881
		$pconfig['csr_dn_commonname'],
882
		['placeholder' => 'e.g. internal-ca']
883
	));
884

    
885
	$section->addInput(new Form_StaticText(
886
		null,
887
		gettext('The following certificate subject components are optional and may be left blank.')
888
	));
889

    
890
	$section->addInput(new Form_Select(
891
		'csr_dn_country',
892
		'Country Code',
893
		$pconfig['csr_dn_country'],
894
		$dn_cc
895
	));
896

    
897
	$section->addInput(new Form_Input(
898
		'csr_dn_state',
899
		'State or Province',
900
		'text',
901
		$pconfig['csr_dn_state'],
902
		['placeholder' => 'e.g. Texas']
903
	));
904

    
905
	$section->addInput(new Form_Input(
906
		'csr_dn_city',
907
		'City',
908
		'text',
909
		$pconfig['csr_dn_city'],
910
		['placeholder' => 'e.g. Austin']
911
	));
912

    
913
	$section->addInput(new Form_Input(
914
		'csr_dn_organization',
915
		'Organization',
916
		'text',
917
		$pconfig['csr_dn_organization'],
918
		['placeholder' => 'e.g. My Company Inc']
919
	));
920

    
921
	$section->addInput(new Form_Input(
922
		'csr_dn_organizationalunit',
923
		'Organizational Unit',
924
		'text',
925
		$pconfig['csr_dn_organizationalunit'],
926
		['placeholder' => 'e.g. My Department Name (optional)']
927
	));
928

    
929
	$form->add($section);
930
	$section = new Form_Section('Choose an Existing Certificate');
931
	$section->addClass('toggle-existing collapse');
932

    
933
	$existCerts = array();
934

    
935
	foreach ($config['cert'] as $cert) {
936
		if (!is_array($cert) || empty($cert)) {
937
			continue;
938
		}
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
	if (!is_array($cert) || empty($cert)) {
1136
		continue;
1137
	}
1138
	$name = htmlspecialchars($cert['descr']);
1139
	$sans = array();
1140
	if ($cert['crt']) {
1141
		$subj = cert_get_subject($cert['crt']);
1142
		$issuer = cert_get_issuer($cert['crt']);
1143
		$purpose = cert_get_purpose($cert['crt']);
1144
		$sans = cert_get_sans($cert['crt']);
1145
		list($startdate, $enddate) = cert_get_dates($cert['crt']);
1146

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

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

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

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

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

    
1285
<nav class="action-buttons">
1286
	<a href="?act=new" class="btn btn-success btn-sm">
1287
		<i class="fa fa-plus icon-embed-btn"></i>
1288
		<?=gettext("Add/Sign")?>
1289
	</a>
1290
</nav>
1291
<?php
1292
	include("foot.inc");
1293
	exit;
1294
}
1295

    
1296

    
1297
?>
1298
<script type="text/javascript">
1299
//<![CDATA[
1300
events.push(function() {
1301

    
1302
<?php if ($internal_ca_count): ?>
1303
	function internalca_change() {
1304

    
1305
		caref = $('#caref').val();
1306

    
1307
		switch (caref) {
1308
<?php
1309
			foreach ($a_ca as $ca):
1310
				if (!$ca['prv']) {
1311
					continue;
1312
				}
1313

    
1314
				$subject = cert_get_subject_hash($ca['crt']);
1315
?>
1316
				case "<?=$ca['refid'];?>":
1317
					$('#dn_country').val(<?=json_encode(cert_escape_x509_chars($subject['C'], true));?>);
1318
					$('#dn_state').val(<?=json_encode(cert_escape_x509_chars($subject['ST'], true));?>);
1319
					$('#dn_city').val(<?=json_encode(cert_escape_x509_chars($subject['L'], true));?>);
1320
					$('#dn_organization').val(<?=json_encode(cert_escape_x509_chars($subject['O'], true));?>);
1321
					$('#dn_organizationalunit').val(<?=json_encode(cert_escape_x509_chars($subject['OU'], true));?>);
1322
					break;
1323
<?php
1324
			endforeach;
1325
?>
1326
		}
1327
	}
1328

    
1329
	function set_csr_ro() {
1330
		var newcsr = ($('#csrtosign').val() == "new");
1331

    
1332
		$('#csrpaste').attr('readonly', !newcsr);
1333
		$('#keypaste').attr('readonly', !newcsr);
1334
		setRequired('csrpaste', newcsr);
1335
	}
1336

    
1337
	// ---------- Click checkbox handlers ---------------------------------------------------------
1338

    
1339
	$('#caref').on('change', function() {
1340
		internalca_change();
1341
	});
1342

    
1343
	$('#csrtosign').change(function () {
1344
		set_csr_ro();
1345
	});
1346

    
1347
	// ---------- On initial page load ------------------------------------------------------------
1348

    
1349
	internalca_change();
1350
	set_csr_ro();
1351

    
1352
	// Suppress "Delete row" button if there are fewer than two rows
1353
	checkLastRow();
1354

    
1355
<?php endif; ?>
1356

    
1357

    
1358
});
1359
//]]>
1360
</script>
1361
<?php
1362
include('foot.inc');
(201-201/234)