Project

General

Profile

Download (42.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-2013 BSD Perimeter
7
 * Copyright (c) 2013-2016 Electric Sheep Fencing
8
 * Copyright (c) 2014-2019 Rubicon Communications, LLC (Netgate)
9
 * Copyright (c) 2008 Shrew Soft Inc
10
 * All rights reserved.
11
 *
12
 * Licensed under the Apache License, Version 2.0 (the "License");
13
 * you may not use this file except in compliance with the License.
14
 * You may obtain a copy of the License at
15
 *
16
 * http://www.apache.org/licenses/LICENSE-2.0
17
 *
18
 * Unless required by applicable law or agreed to in writing, software
19
 * distributed under the License is distributed on an "AS IS" BASIS,
20
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21
 * See the License for the specific language governing permissions and
22
 * limitations under the License.
23
 */
24

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

    
32
require_once("guiconfig.inc");
33
require_once("certs.inc");
34
require_once("pfsense-utils.inc");
35

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

    
43
$cert_keylens = array("1024", "2048", "3072", "4096", "6144", "7680", "8192", "15360", "16384");
44
$cert_keytypes = array("RSA", "ECDSA");
45
$cert_types = array(
46
	"server" => "Server Certificate",
47
	"user" => "User Certificate");
48

    
49
global $cert_altname_types;
50
global $openssl_digest_algs;
51
$openssl_ecnames = openssl_get_curve_names();
52

    
53
if (isset($_REQUEST['userid']) && is_numericint($_REQUEST['userid'])) {
54
	$userid = $_REQUEST['userid'];
55
}
56

    
57
if (isset($userid)) {
58
	$cert_methods["existing"] = gettext("Choose an existing certificate");
59
	init_config_arr(array('system', 'user'));
60
	$a_user =& $config['system']['user'];
61
}
62

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

    
67
init_config_arr(array('ca'));
68
$a_ca = &$config['ca'];
69

    
70
init_config_arr(array('cert'));
71
$a_cert = &$config['cert'];
72

    
73
$internal_ca_count = 0;
74
foreach ($a_ca as $ca) {
75
	if ($ca['prv']) {
76
		$internal_ca_count++;
77
	}
78
}
79

    
80
$act = $_REQUEST['act'];
81

    
82
if ($_POST['act'] == "del") {
83

    
84
	if (!isset($a_cert[$id])) {
85
		pfSenseHeader("system_certmanager.php");
86
		exit;
87
	}
88

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

    
96
if ($act == "new") {
97
	$pconfig['method'] = $_POST['method'];
98
	$pconfig['keytype'] = "RSA";
99
	$pconfig['keylen'] = "2048";
100
	$pconfig['ecname'] = "brainpoolP256r1";
101
	$pconfig['digest_alg'] = "sha256";
102
	$pconfig['csr_keytype'] = "RSA";
103
	$pconfig['csr_keylen'] = "2048";
104
	$pconfig['csr_ecname'] = "brainpoolP256r1";
105
	$pconfig['csr_digest_alg'] = "sha256";
106
	$pconfig['csrsign_digest_alg'] = "sha256";
107
	$pconfig['type'] = "user";
108
	$pconfig['lifetime'] = "3650";
109
}
110

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
250
		if ($pconfig['method'] == "internal") {
251
			$reqdfields = explode(" ",
252
				"descr caref keylen ecname keytype type lifetime dn_commonname");
253
			$reqdfieldsn = array(
254
				gettext("Descriptive name"),
255
				gettext("Certificate authority"),
256
				gettext("Key length"),
257
				gettext("Elliptic Curve Name"),
258
				gettext("Key type"),
259
				gettext("Certificate Type"),
260
				gettext("Lifetime"),
261
				gettext("Common Name"));
262
		}
263

    
264
		if ($pconfig['method'] == "external") {
265
			$reqdfields = explode(" ",
266
				"descr csr_keylen csr_ecname csr_keytype csr_dn_commonname");
267
			$reqdfieldsn = array(
268
				gettext("Descriptive name"),
269
				gettext("Key length"),
270
				gettext("Elliptic Curve Name"),
271
				gettext("Key type"),
272
				gettext("Common Name"));
273
		}
274

    
275
		if ($pconfig['method'] == "existing") {
276
			$reqdfields = array("certref");
277
			$reqdfieldsn = array(gettext("Existing Certificate Choice"));
278
		}
279

    
280
		$altnames = array();
281
		do_input_validation($_POST, $reqdfields, $reqdfieldsn, $input_errors);
282

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

    
302
				if (ctype_digit($entry)) {
303
					$entry++;	// Pre-bootstrap code is one-indexed, but the bootstrap code is 0-indexed
304
					$altnames[$entry][$field] = $value;
305
				}
306
			}
307

    
308
			$pconfig['altnames']['item'] = $altnames;
309

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

    
342
			/* Make sure we do not have invalid characters in the fields for the certificate */
343

    
344
			if (preg_match("/[\?\>\<\&\/\\\"\']/", $_POST['descr'])) {
345
				array_push($input_errors, "The field 'Descriptive Name' contains invalid characters.");
346
			}
347

    
348
			switch ($pconfig['method']) {
349
				case "internal":
350
					if (isset($_POST["keytype"]) && !in_array($_POST["keytype"], $cert_keytypes)) {
351
						array_push($input_errors, gettext("Please select a valid Key Type."));
352
					}
353
					if (isset($_POST["keylen"]) && !in_array($_POST["keylen"], $cert_keylens)) {
354
						array_push($input_errors, gettext("Please select a valid Key Length."));
355
					}
356
					if (isset($_POST["ecname"]) && !in_array($_POST["ecname"], $openssl_ecnames)) {
357
						array_push($input_errors, gettext("Please select a valid Elliptic Curve Name."));
358
					}
359
					if (!in_array($_POST["digest_alg"], $openssl_digest_algs)) {
360
						array_push($input_errors, gettext("Please select a valid Digest Algorithm."));
361
					}
362
					break;
363
				case "external":
364
					if (isset($_POST["csr_keytype"]) && !in_array($_POST["csr_keytype"], $cert_keytypes)) {
365
						array_push($input_errors, gettext("Please select a valid Key Type."));
366
					}
367
					if (isset($_POST["csr_keylen"]) && !in_array($_POST["csr_keylen"], $cert_keylens)) {
368
						array_push($input_errors, gettext("Please select a valid Key Length."));
369
					}
370
					if (isset($_POST["csr_ecname"]) && !in_array($_POST["csr_ecname"], $openssl_ecnames)) {
371
						array_push($input_errors, gettext("Please select a valid Elliptic Curve Name."));
372
					}
373
					if (!in_array($_POST["csr_digest_alg"], $openssl_digest_algs)) {
374
						array_push($input_errors, gettext("Please select a valid Digest Algorithm."));
375
					}
376
					break;
377
				case "sign":
378
					if (!in_array($_POST["csrsign_digest_alg"], $openssl_digest_algs)) {
379
						array_push($input_errors, gettext("Please select a valid Digest Algorithm."));
380
					}
381
					break;
382
				default:
383
					break;
384
			}
385
		}
386

    
387
		/* save modifications */
388
		if (!$input_errors) {
389

    
390
			if ($pconfig['method'] == "existing") {
391
				$cert = lookup_cert($pconfig['certref']);
392
				if ($cert && $a_user) {
393
					$a_user[$userid]['cert'][] = $cert['refid'];
394
				}
395
			} else if ($pconfig['method'] == "sign") { // Sign a CSR
396
				$csrid = lookup_cert($pconfig['csrtosign']);
397
				$ca = & lookup_ca($pconfig['catosignwith']);
398

    
399
				// Read the CSR from $config, or if a new one, from the textarea
400
				if ($pconfig['csrtosign'] === "new") {
401
					$csr = $pconfig['csrpaste'];
402
				} else {
403
					$csr = base64_decode($csrid['csr']);
404
				}
405
				if (count($altnames)) {
406
					foreach ($altnames as $altname) {
407
						$altnames_tmp[] = "{$altname['type']}:" . cert_escape_x509_chars($altname['value']);
408
					}
409
					$altname_str = implode(",", $altnames_tmp);
410
				}
411

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

    
414
				if ($n509) {
415
					// Gather the details required to save the new cert
416
					$newcert = array();
417
					$newcert['refid'] = uniqid();
418
					$newcert['caref'] = $pconfig['catosignwith'];
419
					$newcert['descr'] = $pconfig['descr'];
420
					$newcert['type'] = $pconfig['type'];
421
					$newcert['crt'] = base64_encode($n509);
422

    
423
					if ($pconfig['csrtosign'] === "new") {
424
						$newcert['prv'] = base64_encode($pconfig['keypaste']);
425
					} else {
426
						$newcert['prv'] = $csrid['prv'];
427
					}
428

    
429
					// Add it to the config file
430
					$config['cert'][] = $newcert;
431
				}
432

    
433
			} else {
434
				$cert = array();
435
				$cert['refid'] = uniqid();
436
				if (isset($id) && $a_cert[$id]) {
437
					$cert = $a_cert[$id];
438
				}
439

    
440
				$cert['descr'] = $pconfig['descr'];
441

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

    
444
				if ($pconfig['method'] == "import") {
445
					cert_import($cert, $pconfig['cert'], $pconfig['key']);
446
				}
447

    
448
				if ($pconfig['method'] == "internal") {
449
					$dn = array('commonName' => cert_escape_x509_chars($pconfig['dn_commonname']));
450
					if (!empty($pconfig['dn_country'])) {
451
						$dn['countryName'] = $pconfig['dn_country'];
452
					}
453
					if (!empty($pconfig['dn_state'])) {
454
						$dn['stateOrProvinceName'] = cert_escape_x509_chars($pconfig['dn_state']);
455
					}
456
					if (!empty($pconfig['dn_city'])) {
457
						$dn['localityName'] = cert_escape_x509_chars($pconfig['dn_city']);
458
					}
459
					if (!empty($pconfig['dn_organization'])) {
460
						$dn['organizationName'] = cert_escape_x509_chars($pconfig['dn_organization']);
461
					}
462
					if (!empty($pconfig['dn_organizationalunit'])) {
463
						$dn['organizationalUnitName'] = cert_escape_x509_chars($pconfig['dn_organizationalunit']);
464
					}
465

    
466
					$altnames_tmp = array();
467
					$cn_altname = cert_add_altname_type($pconfig['dn_commonname']);
468
					if (!empty($cn_altname)) {
469
						$altnames_tmp[] = $cn_altname;
470
					}
471
					if (count($altnames)) {
472
						foreach ($altnames as $altname) {
473
							// The CN is added as a SAN automatically, do not add it again.
474
							if ($altname['value'] != $pconfig['dn_commonname']) {
475
								$altnames_tmp[] = "{$altname['type']}:" . cert_escape_x509_chars($altname['value']);
476
							}
477
						}
478
					}
479
					if (!empty($altnames_tmp)) {
480
						$dn['subjectAltName'] = implode(",", $altnames_tmp);
481
					}
482

    
483
					if (!cert_create($cert, $pconfig['caref'], $pconfig['keylen'], $pconfig['lifetime'], $dn, $pconfig['type'], $pconfig['digest_alg'], $pconfig['keytype'], $pconfig['ecname'])) {
484
						$input_errors = array();
485
						while ($ssl_err = openssl_error_string()) {
486
							if (strpos($ssl_err, 'NCONF_get_string:no value') === false) {
487
								array_push($input_errors, "openssl library returns: " . $ssl_err);
488
							}
489
						}
490
					}
491
				}
492

    
493
				if ($pconfig['method'] == "external") {
494
					$dn = array('commonName' => cert_escape_x509_chars($pconfig['csr_dn_commonname']));
495
					if (!empty($pconfig['csr_dn_country'])) {
496
						$dn['countryName'] = $pconfig['csr_dn_country'];
497
					}
498
					if (!empty($pconfig['csr_dn_state'])) {
499
						$dn['stateOrProvinceName'] = cert_escape_x509_chars($pconfig['csr_dn_state']);
500
					}
501
					if (!empty($pconfig['csr_dn_city'])) {
502
						$dn['localityName'] = cert_escape_x509_chars($pconfig['csr_dn_city']);
503
					}
504
					if (!empty($pconfig['csr_dn_organization'])) {
505
						$dn['organizationName'] = cert_escape_x509_chars($pconfig['csr_dn_organization']);
506
					}
507
					if (!empty($pconfig['csr_dn_organizationalunit'])) {
508
						$dn['organizationalUnitName'] = cert_escape_x509_chars($pconfig['csr_dn_organizationalunit']);
509
					}
510

    
511
					$altnames_tmp = array();
512
					$cn_altname = cert_add_altname_type($pconfig['csr_dn_commonname']);
513
					if (!empty($cn_altname)) {
514
						$altnames_tmp[] = $cn_altname;
515
					}
516
					if (count($altnames)) {
517
						foreach ($altnames as $altname) {
518
							// The CN is added as a SAN automatically, do not add it again.
519
							if ($altname['value'] != $pconfig['csr_dn_commonname']) {
520
								$altnames_tmp[] = "{$altname['type']}:" . cert_escape_x509_chars($altname['value']);
521
							}
522
						}
523
					}
524
					if (!empty($altnames_tmp)) {
525
						$dn['subjectAltName'] = implode(",", $altnames_tmp);
526
					}
527

    
528
					if (!csr_generate($cert, $pconfig['csr_keylen'], $dn, $pconfig['type'], $pconfig['csr_digest_alg'], $pconfig['csr_keytype'], $pconfig['csr_ecname'])) {
529
						$input_errors = array();
530
						while ($ssl_err = openssl_error_string()) {
531
							if (strpos($ssl_err, 'NCONF_get_string:no value') === false) {
532
								array_push($input_errors, "openssl library returns: " . $ssl_err);
533
							}
534
						}
535
					}
536
				}
537

    
538
				error_reporting($old_err_level);
539

    
540
				if (isset($id) && $a_cert[$id]) {
541
					$a_cert[$id] = $cert;
542
				} else {
543
					$a_cert[] = $cert;
544
				}
545

    
546
				if (isset($a_user) && isset($userid)) {
547
					$a_user[$userid]['cert'][] = $cert['refid'];
548
				}
549
			}
550

    
551
			if (!$input_errors) {
552
				write_config();
553
			}
554

    
555
			if ((isset($userid) && is_numeric($userid)) && !$input_errors) {
556
				post_redirect("system_usermanager.php", array('act' => 'edit', 'userid' => $userid));
557
				exit;
558
			}
559
		}
560
	}
561

    
562
	if ($_POST['save'] == gettext("Update")) {
563
		unset($input_errors);
564
		$pconfig = $_POST;
565

    
566
		/* input validation */
567
		$reqdfields = explode(" ", "descr cert");
568
		$reqdfieldsn = array(
569
			gettext("Descriptive name"),
570
			gettext("Final Certificate data"));
571

    
572
		do_input_validation($_POST, $reqdfields, $reqdfieldsn, $input_errors);
573

    
574
		if (preg_match("/[\?\>\<\&\/\\\"\']/", $_POST['descr'])) {
575
			array_push($input_errors, "The field 'Descriptive Name' contains invalid characters.");
576
		}
577

    
578
//		old way
579
		/* make sure this csr and certificate subjects match */
580
//		$subj_csr = csr_get_subject($pconfig['csr'], false);
581
//		$subj_cert = cert_get_subject($pconfig['cert'], false);
582
//
583
//		if (!isset($_POST['ignoresubjectmismatch']) && !($_POST['ignoresubjectmismatch'] == "yes")) {
584
//			if (strcmp($subj_csr, $subj_cert)) {
585
//				$input_errors[] = sprintf(gettext("The certificate subject '%s' does not match the signing request subject."), $subj_cert);
586
//				$subject_mismatch = true;
587
//			}
588
//		}
589
		$mod_csr = cert_get_publickey($pconfig['csr'], false, 'csr');
590
		$mod_cert = cert_get_publickey($pconfig['cert'], false);
591

    
592
		if (strcmp($mod_csr, $mod_cert)) {
593
			// simply: if the moduli don't match, then the private key and public key won't match
594
			$input_errors[] = sprintf(gettext("The certificate public key does not match the signing request public key."), $subj_cert);
595
			$subject_mismatch = true;
596
		}
597

    
598
		/* save modifications */
599
		if (!$input_errors) {
600

    
601
			$cert = $a_cert[$id];
602

    
603
			$cert['descr'] = $pconfig['descr'];
604

    
605
			csr_complete($cert, $pconfig['cert']);
606

    
607
			$a_cert[$id] = $cert;
608

    
609
			write_config();
610

    
611
			pfSenseHeader("system_certmanager.php");
612
		}
613
	}
614
}
615

    
616
$pgtitle = array(gettext("System"), gettext("Certificate Manager"), gettext("Certificates"));
617
$pglinks = array("", "system_camanager.php", "system_certmanager.php");
618

    
619
if (($act == "new" || ($_POST['save'] == gettext("Save") && $input_errors)) || ($act == "csr" || ($_POST['save'] == gettext("Update") && $input_errors))) {
620
	$pgtitle[] = gettext('Edit');
621
	$pglinks[] = "@self";
622
}
623
include("head.inc");
624

    
625
if ($input_errors) {
626
	print_input_errors($input_errors);
627
}
628

    
629
if ($savemsg) {
630
	print_info_box($savemsg, 'success');
631
}
632

    
633
$tab_array = array();
634
$tab_array[] = array(gettext("CAs"), false, "system_camanager.php");
635
$tab_array[] = array(gettext("Certificates"), true, "system_certmanager.php");
636
$tab_array[] = array(gettext("Certificate Revocation"), false, "system_crlmanager.php");
637
display_top_tabs($tab_array);
638

    
639
if ($act == "new" || (($_POST['save'] == gettext("Save")) && $input_errors)) {
640
	$form = new Form();
641
	$form->setAction('system_certmanager.php?act=edit');
642

    
643
	if (isset($userid) && $a_user) {
644
		$form->addGlobal(new Form_Input(
645
			'userid',
646
			null,
647
			'hidden',
648
			$userid
649
		));
650
	}
651

    
652
	if (isset($id) && $a_cert[$id]) {
653
		$form->addGlobal(new Form_Input(
654
			'id',
655
			null,
656
			'hidden',
657
			$id
658
		));
659
	}
660

    
661
	$section = new Form_Section('Add/Sign a New Certificate');
662

    
663
	if (!isset($id)) {
664
		$section->addInput(new Form_Select(
665
			'method',
666
			'*Method',
667
			$pconfig['method'],
668
			$cert_methods
669
		))->toggles();
670
	}
671

    
672
	$section->addInput(new Form_Input(
673
		'descr',
674
		'*Descriptive name',
675
		'text',
676
		($a_user && empty($pconfig['descr'])) ? $a_user[$userid]['name'] : $pconfig['descr']
677
	))->addClass('toggle-internal toggle-import toggle-external toggle-sign collapse');
678

    
679
	$form->add($section);
680

    
681
	// Return an array containing the IDs od all CAs
682
	function list_cas() {
683
		global $a_ca;
684
		$allCas = array();
685

    
686
		foreach ($a_ca as $ca) {
687
			if ($ca['prv']) {
688
				$allCas[$ca['refid']] = $ca['descr'];
689
			}
690
		}
691

    
692
		return $allCas;
693
	}
694

    
695
	// Return an array containing the IDs od all CSRs
696
	function list_csrs() {
697
		global $config;
698
		$allCsrs = array();
699

    
700
		foreach ($config['cert'] as $cert) {
701
			if ($cert['csr']) {
702
				$allCsrs[$cert['refid']] = $cert['descr'];
703
			}
704
		}
705

    
706
		return ['new' => gettext('New CSR (Paste below)')] + $allCsrs;
707
	}
708

    
709
	$section = new Form_Section('Sign CSR');
710
	$section->addClass('toggle-sign collapse');
711

    
712
	$section->AddInput(new Form_Select(
713
		'catosignwith',
714
		'*CA to sign with',
715
		$pconfig['catosignwith'],
716
		list_cas()
717
	));
718

    
719
	$section->AddInput(new Form_Select(
720
		'csrtosign',
721
		'*CSR to sign',
722
		isset($pconfig['csrtosign']) ? $pconfig['csrtosign'] : 'new',
723
		list_csrs()
724
	));
725

    
726
	$section->addInput(new Form_Textarea(
727
		'csrpaste',
728
		'CSR data',
729
		$pconfig['csrpaste']
730
	))->setHelp('Paste a Certificate Signing Request in X.509 PEM format here.');
731

    
732
	$section->addInput(new Form_Textarea(
733
		'keypaste',
734
		'Key data',
735
		$pconfig['keypaste']
736
	))->setHelp('Optionally paste a private key here. The key will be associated with the newly signed certificate in pfSense');
737

    
738
	$section->addInput(new Form_Input(
739
		'csrsign_lifetime',
740
		'*Certificate Lifetime (days)',
741
		'number',
742
		$pconfig['csrsign_lifetime'] ? $pconfig['csrsign_lifetime']:'3650'
743
	));
744
	$section->addInput(new Form_Select(
745
		'csrsign_digest_alg',
746
		'*Digest Algorithm',
747
		$pconfig['csrsign_digest_alg'],
748
		array_combine($openssl_digest_algs, $openssl_digest_algs)
749
	))->setHelp('NOTE: It is recommended to use an algorithm stronger than '.
750
		'SHA1 when possible');
751

    
752
	$form->add($section);
753

    
754
	$section = new Form_Section('Import Certificate');
755
	$section->addClass('toggle-import collapse');
756

    
757
	$section->addInput(new Form_Textarea(
758
		'cert',
759
		'*Certificate data',
760
		$pconfig['cert']
761
	))->setHelp('Paste a certificate in X.509 PEM format here.');
762

    
763
	$section->addInput(new Form_Textarea(
764
		'key',
765
		'*Private key data',
766
		$pconfig['key']
767
	))->setHelp('Paste a private key in X.509 PEM format here.');
768

    
769
	$form->add($section);
770
	$section = new Form_Section('Internal Certificate');
771
	$section->addClass('toggle-internal collapse');
772

    
773
	if (!$internal_ca_count) {
774
		$section->addInput(new Form_StaticText(
775
			'*Certificate authority',
776
			gettext('No internal Certificate Authorities have been defined. ') .
777
			gettext('An internal CA must be defined in order to create an internal certificate. ') .
778
			sprintf(gettext('%1$sCreate%2$s an internal CA.'), '<a href="system_camanager.php?act=new&amp;method=internal"> ', '</a>')
779
		));
780
	} else {
781
		$allCas = array();
782
		foreach ($a_ca as $ca) {
783
			if (!$ca['prv']) {
784
				continue;
785
			}
786

    
787
			$allCas[ $ca['refid'] ] = $ca['descr'];
788
		}
789

    
790
		$section->addInput(new Form_Select(
791
			'caref',
792
			'*Certificate authority',
793
			$pconfig['caref'],
794
			$allCas
795
		));
796
	}
797

    
798
	$section->addInput(new Form_Select(
799
		'keytype',
800
		'*Key type',
801
		$pconfig['keytype'],
802
		array_combine($cert_keytypes, $cert_keytypes)
803
	));
804

    
805
	$group = new Form_Group($i == 0 ? '*Key length':'');
806
	$group->addClass('rsakeys');
807
	$group->add(new Form_Select(
808
		'keylen',
809
		null,
810
		$pconfig['keylen'],
811
		array_combine($cert_keylens, $cert_keylens)
812
	));
813
	$section->add($group);
814

    
815
	$group = new Form_Group($i == 0 ? '*Elliptic Curve Name':'');
816
	$group->addClass('ecnames');
817
	$group->add(new Form_Select(
818
		'ecname',
819
		null,
820
		$pconfig['ecname'],
821
		array_combine($openssl_ecnames, $openssl_ecnames)
822
	));
823
	$section->add($group);
824

    
825
	$section->addInput(new Form_Select(
826
		'digest_alg',
827
		'*Digest Algorithm',
828
		$pconfig['digest_alg'],
829
		array_combine($openssl_digest_algs, $openssl_digest_algs)
830
	))->setHelp('NOTE: It is recommended to use an algorithm stronger than '.
831
		'SHA1 when possible.');
832

    
833
	$section->addInput(new Form_Input(
834
		'lifetime',
835
		'*Lifetime (days)',
836
		'number',
837
		$pconfig['lifetime']
838
	));
839

    
840
	$section->addInput(new Form_Input(
841
		'dn_commonname',
842
		'*Common Name',
843
		'text',
844
		$pconfig['dn_commonname'],
845
		['placeholder' => 'e.g. www.example.com']
846
	));
847

    
848
	$section->addInput(new Form_StaticText(
849
		null,
850
		gettext('The following certificate subject components are optional and may be left blank.')
851
	));
852

    
853
	$section->addInput(new Form_Select(
854
		'dn_country',
855
		'Country Code',
856
		$pconfig['dn_country'],
857
		get_cert_country_codes()
858
	));
859

    
860
	$section->addInput(new Form_Input(
861
		'dn_state',
862
		'State or Province',
863
		'text',
864
		$pconfig['dn_state'],
865
		['placeholder' => 'e.g. Texas']
866
	));
867

    
868
	$section->addInput(new Form_Input(
869
		'dn_city',
870
		'City',
871
		'text',
872
		$pconfig['dn_city'],
873
		['placeholder' => 'e.g. Austin']
874
	));
875

    
876
	$section->addInput(new Form_Input(
877
		'dn_organization',
878
		'Organization',
879
		'text',
880
		$pconfig['dn_organization'],
881
		['placeholder' => 'e.g. My Company Inc']
882
	));
883

    
884
	$section->addInput(new Form_Input(
885
		'dn_organizationalunit',
886
		'Organizational Unit',
887
		'text',
888
		$pconfig['dn_organizationalunit'],
889
		['placeholder' => 'e.g. My Department Name (optional)']
890
	));
891

    
892
	$form->add($section);
893
	$section = new Form_Section('External Signing Request');
894
	$section->addClass('toggle-external collapse');
895

    
896
	$section->addInput(new Form_Select(
897
		'csr_keytype',
898
		'*Key type',
899
		$pconfig['csr_keytype'],
900
		array_combine($cert_keytypes, $cert_keytypes)
901
	));
902

    
903
	$group = new Form_Group($i == 0 ? '*Key length':'');
904
	$group->addClass('csr_rsakeys');
905
	$group->add(new Form_Select(
906
		'csr_keylen',
907
		null,
908
		$pconfig['csr_keylen'],
909
		array_combine($cert_keylens, $cert_keylens)
910
	));
911
	$section->add($group);
912

    
913
	$group = new Form_Group($i == 0 ? '*Elliptic Curve Name':'');
914
	$group->addClass('csr_ecnames');
915
	$group->add(new Form_Select(
916
		'csr_ecname',
917
		null,
918
		$pconfig['csr_ecname'],
919
		array_combine($openssl_ecnames, $openssl_ecnames)
920
	));
921
	$section->add($group);
922

    
923
	$section->addInput(new Form_Select(
924
		'csr_digest_alg',
925
		'*Digest Algorithm',
926
		$pconfig['csr_digest_alg'],
927
		array_combine($openssl_digest_algs, $openssl_digest_algs)
928
	))->setHelp('NOTE: It is recommended to use an algorithm stronger than '.
929
		'SHA1 when possible');
930

    
931
	$section->addInput(new Form_Input(
932
		'csr_dn_commonname',
933
		'*Common Name',
934
		'text',
935
		$pconfig['csr_dn_commonname'],
936
		['placeholder' => 'e.g. internal-ca']
937
	));
938

    
939
	$section->addInput(new Form_StaticText(
940
		null,
941
		gettext('The following certificate subject components are optional and may be left blank.')
942
	));
943

    
944
	$section->addInput(new Form_Select(
945
		'csr_dn_country',
946
		'Country Code',
947
		$pconfig['csr_dn_country'],
948
		get_cert_country_codes()
949
	));
950

    
951
	$section->addInput(new Form_Input(
952
		'csr_dn_state',
953
		'State or Province',
954
		'text',
955
		$pconfig['csr_dn_state'],
956
		['placeholder' => 'e.g. Texas']
957
	));
958

    
959
	$section->addInput(new Form_Input(
960
		'csr_dn_city',
961
		'City',
962
		'text',
963
		$pconfig['csr_dn_city'],
964
		['placeholder' => 'e.g. Austin']
965
	));
966

    
967
	$section->addInput(new Form_Input(
968
		'csr_dn_organization',
969
		'Organization',
970
		'text',
971
		$pconfig['csr_dn_organization'],
972
		['placeholder' => 'e.g. My Company Inc']
973
	));
974

    
975
	$section->addInput(new Form_Input(
976
		'csr_dn_organizationalunit',
977
		'Organizational Unit',
978
		'text',
979
		$pconfig['csr_dn_organizationalunit'],
980
		['placeholder' => 'e.g. My Department Name (optional)']
981
	));
982

    
983
	$form->add($section);
984
	$section = new Form_Section('Choose an Existing Certificate');
985
	$section->addClass('toggle-existing collapse');
986

    
987
	$existCerts = array();
988

    
989
	foreach ($config['cert'] as $cert) {
990
		if (!is_array($cert) || empty($cert)) {
991
			continue;
992
		}
993
		if (is_array($config['system']['user'][$userid]['cert'])) { // Could be MIA!
994
			if (isset($userid) && in_array($cert['refid'], $config['system']['user'][$userid]['cert'])) {
995
				continue;
996
			}
997
		}
998

    
999
		$ca = lookup_ca($cert['caref']);
1000
		if ($ca) {
1001
			$cert['descr'] .= " (CA: {$ca['descr']})";
1002
		}
1003

    
1004
		if (cert_in_use($cert['refid'])) {
1005
			$cert['descr'] .= " (In Use)";
1006
		}
1007
		if (is_cert_revoked($cert)) {
1008
			$cert['descr'] .= " (Revoked)";
1009
		}
1010

    
1011
		$existCerts[ $cert['refid'] ] = $cert['descr'];
1012
	}
1013

    
1014
	$section->addInput(new Form_Select(
1015
		'certref',
1016
		'*Existing Certificates',
1017
		$pconfig['certref'],
1018
		$existCerts
1019
	));
1020

    
1021
	$form->add($section);
1022

    
1023
	$section = new Form_Section('Certificate Attributes');
1024
	$section->addClass('toggle-external toggle-internal toggle-sign collapse');
1025

    
1026
	$section->addInput(new Form_StaticText(
1027
		gettext('Attribute Notes'),
1028
		'<span class="help-block">'.
1029
		gettext('The following attributes are added to certificates and ' .
1030
		'requests when they are created or signed. These attributes behave ' .
1031
		'differently depending on the selected mode.') .
1032
		'<br/><br/>' .
1033
		'<span class="toggle-internal collapse">' . gettext('For Internal Certificates, these attributes are added directly to the certificate as shown.') . '</span>' .
1034
		'<span class="toggle-external collapse">' .
1035
		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. ') .
1036
		'<br/><br/>' .
1037
		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>' .
1038
		'<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>' .
1039
		'</span>'
1040
	));
1041

    
1042
	$section->addInput(new Form_Select(
1043
		'type',
1044
		'*Certificate Type',
1045
		$pconfig['type'],
1046
		$cert_types
1047
	))->setHelp('Add type-specific usage attributes to the signed certificate.' .
1048
		' Used for placing usage restrictions on, or granting abilities to, ' .
1049
		'the signed certificate.');
1050

    
1051
	if (empty($pconfig['altnames']['item'])) {
1052
		$pconfig['altnames']['item'] = array(
1053
			array('type' => null, 'value' => null)
1054
		);
1055
	}
1056

    
1057
	$counter = 0;
1058
	$numrows = count($pconfig['altnames']['item']) - 1;
1059

    
1060
	foreach ($pconfig['altnames']['item'] as $item) {
1061

    
1062
		$group = new Form_Group($counter == 0 ? 'Alternative Names':'');
1063

    
1064
		$group->add(new Form_Select(
1065
			'altname_type' . $counter,
1066
			'Type',
1067
			$item['type'],
1068
			$cert_altname_types
1069
		))->setHelp(($counter == $numrows) ? 'Type':null);
1070

    
1071
		$group->add(new Form_Input(
1072
			'altname_value' . $counter,
1073
			null,
1074
			'text',
1075
			$item['value']
1076
		))->setHelp(($counter == $numrows) ? 'Value':null);
1077

    
1078
		$group->add(new Form_Button(
1079
			'deleterow' . $counter,
1080
			'Delete',
1081
			null,
1082
			'fa-trash'
1083
		))->addClass('btn-warning');
1084

    
1085
		$group->addClass('repeatable');
1086

    
1087
		$group->setHelp('Enter additional identifiers for the certificate ' .
1088
			'in this list. The Common Name field is automatically ' .
1089
			'added to the certificate as an Alternative Name. ' .
1090
			'The signing CA may ignore or change these values.');
1091

    
1092
		$section->add($group);
1093

    
1094
		$counter++;
1095
	}
1096

    
1097
	$section->addInput(new Form_Button(
1098
		'addrow',
1099
		'Add',
1100
		null,
1101
		'fa-plus'
1102
	))->addClass('btn-success');
1103

    
1104
	$form->add($section);
1105

    
1106

    
1107
	print $form;
1108

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

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

    
1115
	$section->addInput(new Form_Input(
1116
		'descr',
1117
		'*Descriptive name',
1118
		'text',
1119
		$pconfig['descr']
1120
	));
1121

    
1122
	$section->addInput(new Form_Textarea(
1123
		'csr',
1124
		'Signing request data',
1125
		$pconfig['csr']
1126
	))->setReadonly()
1127
	  ->setWidth(7)
1128
	  ->setHelp('Copy the certificate signing data from here and forward it to a certificate authority for signing.');
1129

    
1130
	$section->addInput(new Form_Textarea(
1131
		'cert',
1132
		'*Final certificate data',
1133
		$pconfig['cert']
1134
	))->setWidth(7)
1135
	  ->setHelp('Paste the certificate received from the certificate authority here.');
1136

    
1137
	if (isset($id) && $a_cert[$id]) {
1138
		$form->addGlobal(new Form_Input(
1139
			'id',
1140
			null,
1141
			'hidden',
1142
			$id
1143
		));
1144

    
1145
		$form->addGlobal(new Form_Input(
1146
			'act',
1147
			null,
1148
			'hidden',
1149
			'csr'
1150
		));
1151
	}
1152

    
1153
	$form->add($section);
1154

    
1155
	$form->addGlobal(new Form_Button(
1156
		'save',
1157
		'Update',
1158
		null,
1159
		'fa-save'
1160
	))->addClass('btn-primary');
1161

    
1162
	print($form);
1163
} else {
1164
?>
1165
<div class="panel panel-default" id="search-panel">
1166
	<div class="panel-heading">
1167
		<h2 class="panel-title">
1168
			<?=gettext('Search')?>
1169
			<span class="widget-heading-icon pull-right">
1170
				<a data-toggle="collapse" href="#search-panel_panel-body">
1171
					<i class="fa fa-plus-circle"></i>
1172
				</a>
1173
			</span>
1174
		</h2>
1175
	</div>
1176
	<div id="search-panel_panel-body" class="panel-body collapse in">
1177
		<div class="form-group">
1178
			<label class="col-sm-2 control-label">
1179
				<?=gettext("Search term")?>
1180
			</label>
1181
			<div class="col-sm-5"><input class="form-control" name="searchstr" id="searchstr" type="text"/></div>
1182
			<div class="col-sm-2">
1183
				<select id="where" class="form-control">
1184
					<option value="0"><?=gettext("Name")?></option>
1185
					<option value="1"><?=gettext("Distinguished Name")?></option>
1186
					<option value="2" selected><?=gettext("Both")?></option>
1187
				</select>
1188
			</div>
1189
			<div class="col-sm-3">
1190
				<a id="btnsearch" title="<?=gettext("Search")?>" class="btn btn-primary btn-sm"><i class="fa fa-search icon-embed-btn"></i><?=gettext("Search")?></a>
1191
				<a id="btnclear" title="<?=gettext("Clear")?>" class="btn btn-info btn-sm"><i class="fa fa-undo icon-embed-btn"></i><?=gettext("Clear")?></a>
1192
			</div>
1193
			<div class="col-sm-10 col-sm-offset-2">
1194
				<span class="help-block"><?=gettext('Enter a search string or *nix regular expression to search certificate names and distinguished names.')?></span>
1195
			</div>
1196
		</div>
1197
	</div>
1198
</div>
1199
<div class="panel panel-default">
1200
	<div class="panel-heading"><h2 class="panel-title"><?=gettext('Certificates')?></h2></div>
1201
	<div class="panel-body">
1202
		<div class="table-responsive">
1203
		<table class="table table-striped table-hover sortable-theme-bootstrap" data-sortable>
1204
			<thead>
1205
				<tr>
1206
					<th><?=gettext("Name")?></th>
1207
					<th><?=gettext("Issuer")?></th>
1208
					<th><?=gettext("Distinguished Name")?></th>
1209
					<th><?=gettext("In Use")?></th>
1210

    
1211
					<th class="col-sm-2"><?=gettext("Actions")?></th>
1212
				</tr>
1213
			</thead>
1214
			<tbody>
1215
<?php
1216

    
1217
$pluginparams = array();
1218
$pluginparams['type'] = 'certificates';
1219
$pluginparams['event'] = 'used_certificates';
1220
$certificates_used_by_packages = pkg_call_plugins('plugin_certificates', $pluginparams);
1221
$i = 0;
1222
foreach ($a_cert as $i => $cert):
1223
	if (!is_array($cert) || empty($cert)) {
1224
		continue;
1225
	}
1226
	$name = htmlspecialchars($cert['descr']);
1227
	if ($cert['crt']) {
1228
		$subj = cert_get_subject($cert['crt']);
1229
		$issuer = cert_get_issuer($cert['crt']);
1230
		$purpose = cert_get_purpose($cert['crt']);
1231

    
1232
		if ($subj == $issuer) {
1233
			$caname = '<i>'. gettext("self-signed") .'</i>';
1234
		} else {
1235
			$caname = '<i>'. gettext("external").'</i>';
1236
		}
1237

    
1238
		$subj = htmlspecialchars(cert_escape_x509_chars($subj, true));
1239
	} else {
1240
		$subj = "";
1241
		$issuer = "";
1242
		$purpose = "";
1243
		$startdate = "";
1244
		$enddate = "";
1245
		$caname = "<em>" . gettext("private key only") . "</em>";
1246
	}
1247

    
1248
	if ($cert['csr']) {
1249
		$subj = htmlspecialchars(cert_escape_x509_chars(csr_get_subject($cert['csr']), true));
1250
		$caname = "<em>" . gettext("external - signature pending") . "</em>";
1251
	}
1252

    
1253
	$ca = lookup_ca($cert['caref']);
1254
	if ($ca) {
1255
		$caname = $ca['descr'];
1256
	}
1257
?>
1258
				<tr>
1259
					<td>
1260
						<?=$name?><br />
1261
						<?php if ($cert['type']): ?>
1262
							<i><?=$cert_types[$cert['type']]?></i><br />
1263
						<?php endif?>
1264
						<?php if (is_array($purpose)): ?>
1265
							CA: <b><?=$purpose['ca']?></b><br/>
1266
							<?=gettext("Server")?>: <b><?=$purpose['server']?></b><br/>
1267
						<?php endif?>
1268
					</td>
1269
					<td><?=$caname?></td>
1270
					<td>
1271
						<?=$subj?>
1272
						<?= cert_print_infoblock($cert); ?>
1273
						<?php cert_print_dates($cert);?>
1274
					</td>
1275
					<td>
1276
						<?php if (is_cert_revoked($cert)): ?>
1277
							<i><?=gettext("Revoked")?></i>
1278
						<?php endif?>
1279
						<?php if (is_webgui_cert($cert['refid'])): ?>
1280
							<?=gettext("webConfigurator")?>
1281
						<?php endif?>
1282
						<?php if (is_user_cert($cert['refid'])): ?>
1283
							<?=gettext("User Cert")?>
1284
						<?php endif?>
1285
						<?php if (is_openvpn_server_cert($cert['refid'])): ?>
1286
							<?=gettext("OpenVPN Server")?>
1287
						<?php endif?>
1288
						<?php if (is_openvpn_client_cert($cert['refid'])): ?>
1289
							<?=gettext("OpenVPN Client")?>
1290
						<?php endif?>
1291
						<?php if (is_ipsec_cert($cert['refid'])): ?>
1292
							<?=gettext("IPsec Tunnel")?>
1293
						<?php endif?>
1294
						<?php if (is_captiveportal_cert($cert['refid'])): ?>
1295
							<?=gettext("Captive Portal")?>
1296
						<?php endif?>
1297
						<?php echo cert_usedby_description($cert['refid'], $certificates_used_by_packages); ?>
1298
					</td>
1299
					<td>
1300
						<?php if (!$cert['csr']): ?>
1301
							<a href="system_certmanager.php?act=exp&amp;id=<?=$i?>" class="fa fa-certificate" title="<?=gettext("Export Certificate")?>"></a>
1302
							<?php if ($cert['prv']): ?>
1303
								<a href="system_certmanager.php?act=key&amp;id=<?=$i?>" class="fa fa-key" title="<?=gettext("Export Key")?>"></a>
1304
							<?php endif?>
1305
							<?php if (is_cert_locally_renewable($cert)): ?>
1306
								<a href="system_certmanager_renew.php?type=cert&amp;refid=<?=$cert['refid']?>" class="fa fa-repeat" title="<?=gettext("Reissue/Renew")?>"></a>
1307
							<?php endif ?>
1308
							<a href="system_certmanager.php?act=p12&amp;id=<?=$i?>" class="fa fa-archive" title="<?=gettext("Export P12")?>"></a>
1309
						<?php else: ?>
1310
							<a href="system_certmanager.php?act=csr&amp;id=<?=$i?>" class="fa fa-pencil" title="<?=gettext("Update CSR")?>"></a>
1311
							<a href="system_certmanager.php?act=req&amp;id=<?=$i?>" class="fa fa-sign-in" title="<?=gettext("Export Request")?>"></a>
1312
							<a href="system_certmanager.php?act=key&amp;id=<?=$i?>" class="fa fa-key" title="<?=gettext("Export Key")?>"></a>
1313
						<?php endif?>
1314
						<?php if (!cert_in_use($cert['refid'])): ?>
1315
							<a href="system_certmanager.php?act=del&amp;id=<?=$i?>" class="fa fa-trash" title="<?=gettext("Delete Certificate")?>" usepost></a>
1316
						<?php endif?>
1317
					</td>
1318
				</tr>
1319
<?php
1320
	$i++;
1321
	endforeach; ?>
1322
			</tbody>
1323
		</table>
1324
		</div>
1325
	</div>
1326
</div>
1327

    
1328
<nav class="action-buttons">
1329
	<a href="?act=new" class="btn btn-success btn-sm">
1330
		<i class="fa fa-plus icon-embed-btn"></i>
1331
		<?=gettext("Add/Sign")?>
1332
	</a>
1333
</nav>
1334
<script type="text/javascript">
1335
//<![CDATA[
1336

    
1337
events.push(function() {
1338

    
1339
	// Make these controls plain buttons
1340
	$("#btnsearch").prop('type', 'button');
1341
	$("#btnclear").prop('type', 'button');
1342

    
1343
	// Search for a term in the entry name and/or dn
1344
	$("#btnsearch").click(function() {
1345
		var searchstr = $('#searchstr').val().toLowerCase();
1346
		var table = $("table tbody");
1347
		var where = $('#where').val();
1348

    
1349
		table.find('tr').each(function (i) {
1350
			var $tds = $(this).find('td'),
1351
				shortname = $tds.eq(0).text().trim().toLowerCase(),
1352
				dn = $tds.eq(2).text().trim().toLowerCase();
1353

    
1354
			regexp = new RegExp(searchstr);
1355
			if (searchstr.length > 0) {
1356
				if (!(regexp.test(shortname) && (where != 1)) && !(regexp.test(dn) && (where != 0))) {
1357
					$(this).hide();
1358
				} else {
1359
					$(this).show();
1360
				}
1361
			} else {
1362
				$(this).show();	// A blank search string shows all
1363
			}
1364
		});
1365
	});
1366

    
1367
	// Clear the search term and unhide all rows (that were hidden during a previous search)
1368
	$("#btnclear").click(function() {
1369
		var table = $("table tbody");
1370

    
1371
		$('#searchstr').val("");
1372

    
1373
		table.find('tr').each(function (i) {
1374
			$(this).show();
1375
		});
1376
	});
1377

    
1378
	// Hitting the enter key will do the same as clicking the search button
1379
	$("#searchstr").on("keyup", function (event) {
1380
		if (event.keyCode == 13) {
1381
			$("#btnsearch").get(0).click();
1382
		}
1383
	});
1384
});
1385
//]]>
1386
</script>
1387
<?php
1388
	include("foot.inc");
1389
	exit;
1390
}
1391

    
1392

    
1393
?>
1394
<script type="text/javascript">
1395
//<![CDATA[
1396
events.push(function() {
1397

    
1398
<?php if ($internal_ca_count): ?>
1399
	function internalca_change() {
1400

    
1401
		caref = $('#caref').val();
1402

    
1403
		switch (caref) {
1404
<?php
1405
			foreach ($a_ca as $ca):
1406
				if (!$ca['prv']) {
1407
					continue;
1408
				}
1409

    
1410
				$subject = cert_get_subject_hash($ca['crt']);
1411
?>
1412
				case "<?=$ca['refid'];?>":
1413
					$('#dn_country').val(<?=json_encode(cert_escape_x509_chars($subject['C'], true));?>);
1414
					$('#dn_state').val(<?=json_encode(cert_escape_x509_chars($subject['ST'], true));?>);
1415
					$('#dn_city').val(<?=json_encode(cert_escape_x509_chars($subject['L'], true));?>);
1416
					$('#dn_organization').val(<?=json_encode(cert_escape_x509_chars($subject['O'], true));?>);
1417
					$('#dn_organizationalunit').val(<?=json_encode(cert_escape_x509_chars($subject['OU'], true));?>);
1418
					break;
1419
<?php
1420
			endforeach;
1421
?>
1422
		}
1423
	}
1424

    
1425
	function set_csr_ro() {
1426
		var newcsr = ($('#csrtosign').val() == "new");
1427

    
1428
		$('#csrpaste').attr('readonly', !newcsr);
1429
		$('#keypaste').attr('readonly', !newcsr);
1430
		setRequired('csrpaste', newcsr);
1431
	}
1432

    
1433
	// ---------- Click checkbox handlers ---------------------------------------------------------
1434

    
1435
	$('#caref').on('change', function() {
1436
		internalca_change();
1437
	});
1438

    
1439
	$('#csrtosign').change(function () {
1440
		set_csr_ro();
1441
	});
1442

    
1443
	function change_keytype() {
1444
       		hideClass('rsakeys', ($('#keytype').val() != 'RSA'));
1445
       		hideClass('ecnames', ($('#keytype').val() != 'ECDSA'));
1446
        }
1447

    
1448
	$('#keytype').change(function () {
1449
                change_keytype();
1450
        });
1451

    
1452
	function change_csrkeytype() {
1453
       		hideClass('csr_rsakeys', ($('#csr_keytype').val() != 'RSA'));
1454
       		hideClass('csr_ecnames', ($('#csr_keytype').val() != 'ECDSA'));
1455
        }
1456

    
1457
	$('#csr_keytype').change(function () {
1458
                change_csrkeytype();
1459
        });
1460

    
1461
	// ---------- On initial page load ------------------------------------------------------------
1462

    
1463
	internalca_change();
1464
	set_csr_ro();
1465
	change_keytype();
1466
	change_csrkeytype();
1467

    
1468
	// Suppress "Delete row" button if there are fewer than two rows
1469
	checkLastRow();
1470

    
1471

    
1472
<?php endif; ?>
1473

    
1474

    
1475
});
1476
//]]>
1477
</script>
1478
<?php
1479
include('foot.inc');
(193-193/227)