Project

General

Profile

Download (53 KB) Statistics
| Branch: | Tag: | Revision:
1 64cc39d3 Matthew Grooms
<?php
2
/*
3 c5d81585 Renato Botelho
 * system_certmanager.php
4 98402844 Stephen Beaver
 *
5 c5d81585 Renato Botelho
 * part of pfSense (https://www.pfsense.org)
6 38809d47 Renato Botelho do Couto
 * Copyright (c) 2004-2013 BSD Perimeter
7
 * Copyright (c) 2013-2016 Electric Sheep Fencing
8 8f585441 Luiz Souza
 * Copyright (c) 2014-2021 Rubicon Communications, LLC (Netgate)
9 c5d81585 Renato Botelho
 * Copyright (c) 2008 Shrew Soft Inc
10
 * All rights reserved.
11 98402844 Stephen Beaver
 *
12 b12ea3fb Renato Botelho
 * 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 98402844 Stephen Beaver
 *
16 b12ea3fb Renato Botelho
 * http://www.apache.org/licenses/LICENSE-2.0
17 98402844 Stephen Beaver
 *
18 b12ea3fb Renato Botelho
 * 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 98402844 Stephen Beaver
 */
24 64cc39d3 Matthew Grooms
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 c81ef6e2 Phil Davis
require_once("guiconfig.inc");
33 14f5ae08 Ermal Lu?i
require_once("certs.inc");
34 fdd8fafc doktornotor
require_once("pfsense-utils.inc");
35 64cc39d3 Matthew Grooms
36
$cert_methods = array(
37 a37753d7 Vinicius Coque
	"internal" => gettext("Create an internal Certificate"),
38 b0a5c280 jim-p
	"import" => gettext("Import an existing Certificate"),
39 ad9b5c67 jim-p
	"external" => gettext("Create a Certificate Signing Request"),
40 2052d3e2 Steve Beaver
	"sign" => gettext("Sign a Certificate Signing Request")
41 ad9b5c67 jim-p
);
42 64cc39d3 Matthew Grooms
43 36cfae5f Justin Coffman
$cert_keylens = array("1024", "2048", "3072", "4096", "6144", "7680", "8192", "15360", "16384");
44 47c46bbd Viktor Gurov
$cert_keytypes = array("RSA", "ECDSA");
45 56b1ed39 Phil Davis
$cert_types = array(
46
	"server" => "Server Certificate",
47
	"user" => "User Certificate");
48 64cc39d3 Matthew Grooms
49 2e1809dd jim-p
global $cert_altname_types;
50 84141846 jim-p
global $openssl_digest_algs;
51 3f0b7bc3 jim-p
global $cert_strict_values;
52 3a877e4a jim-p
$max_lifetime = cert_get_max_lifetime();
53
$default_lifetime = min(3650, $max_lifetime);
54 cffcf9bf jim-p
$openssl_ecnames = cert_build_curve_list();
55 f0b38e39 jim-p
$class = "success";
56 2f65de89 jim-p
57 12e3e735 jim-p
if (isset($_REQUEST['userid']) && is_numericint($_REQUEST['userid'])) {
58 4611e283 Steve Beaver
	$userid = $_REQUEST['userid'];
59 56b1ed39 Phil Davis
}
60 e41ec584 Renato Botelho
61
if (isset($userid)) {
62 ad9b5c67 jim-p
	$cert_methods["existing"] = gettext("Choose an existing certificate");
63 c6c398c6 jim-p
	init_config_arr(array('system', 'user'));
64 ad9b5c67 jim-p
	$a_user =& $config['system']['user'];
65
}
66
67 c6c398c6 jim-p
init_config_arr(array('ca'));
68
$a_ca = &$config['ca'];
69 64cc39d3 Matthew Grooms
70 c6c398c6 jim-p
init_config_arr(array('cert'));
71
$a_cert = &$config['cert'];
72 64cc39d3 Matthew Grooms
73
$internal_ca_count = 0;
74 56b1ed39 Phil Davis
foreach ($a_ca as $ca) {
75
	if ($ca['prv']) {
76 64cc39d3 Matthew Grooms
		$internal_ca_count++;
77 56b1ed39 Phil Davis
	}
78
}
79 64cc39d3 Matthew Grooms
80 96773352 jim-p
if ($_REQUEST['exportp12']) {
81
	$act = 'p12';
82
} elseif ($_REQUEST['exportpkey']) {
83
	$act = 'key';
84
} else {
85
	$act = $_REQUEST['act'];
86
}
87
88
if ($act == 'edit') {
89
	$cert_methods = array(
90
		'edit' => gettext("Edit an existing certificate")
91
	);
92
}
93 8b35eae5 Stephen Beaver
94 f0b38e39 jim-p
if (isset($_REQUEST['id']) && ctype_alnum($_REQUEST['id'])) {
95
	$id = $_REQUEST['id'];
96
}
97
if (!empty($id)) {
98
	$thiscert =& lookup_cert($id);
99
}
100
101 7e83055a jim-p
/* Actions other than 'new' require an ID.
102
 * 'del' action must be submitted via POST. */
103
if ((!empty($act) &&
104
    ($act != 'new') &&
105 f0b38e39 jim-p
    !$thiscert) ||
106 7e83055a jim-p
    (($act == 'del') && empty($_POST))) {
107 2f51259b jim-p
	pfSenseHeader("system_certmanager.php");
108
	exit;
109 64cc39d3 Matthew Grooms
}
110
111 7e83055a jim-p
switch ($act) {
112
	case 'del':
113 f0b38e39 jim-p
		$name = htmlspecialchars($thiscert['descr']);
114
		if (cert_in_use($id)) {
115
			$savemsg = sprintf(gettext("Certificate %s is in use and cannot be deleted"), $name);
116
			$class = "danger";
117
		} else {
118
			foreach ($a_cert as $cid => $acrt) {
119
				if ($acrt['refid'] == $thiscert['refid']) {
120
					unset($a_cert[$cid]);
121
				}
122
			}
123
			$savemsg = sprintf(gettext("Deleted certificate %s"), $name);
124
			write_config($savemsg);
125
		}
126
		unset($act);
127
		break;
128 7e83055a jim-p
	case 'new':
129
		/* New certificate, so set default values */
130
		$pconfig['method'] = $_POST['method'];
131
		$pconfig['keytype'] = "RSA";
132
		$pconfig['keylen'] = "2048";
133 c3cda38e jim-p
		$pconfig['ecname'] = "prime256v1";
134 7e83055a jim-p
		$pconfig['digest_alg'] = "sha256";
135
		$pconfig['csr_keytype'] = "RSA";
136
		$pconfig['csr_keylen'] = "2048";
137 c3cda38e jim-p
		$pconfig['csr_ecname'] = "prime256v1";
138 7e83055a jim-p
		$pconfig['csr_digest_alg'] = "sha256";
139
		$pconfig['csrsign_digest_alg'] = "sha256";
140
		$pconfig['type'] = "user";
141
		$pconfig['lifetime'] = $default_lifetime;
142
		break;
143 96773352 jim-p
	case 'edit':
144
		/* Editing a certificate, so populate values */
145
		$pconfig['descr'] = $thiscert['descr'];
146
		$pconfig['cert'] = base64_decode($thiscert['crt']);
147
		$pconfig['key'] = base64_decode($thiscert['prv']);
148
		break;
149 7e83055a jim-p
	case 'csr':
150
		/* Editing a CSR, so populate values */
151 f0b38e39 jim-p
		$pconfig['descr'] = $thiscert['descr'];
152
		$pconfig['csr'] = base64_decode($thiscert['csr']);
153 7e83055a jim-p
		break;
154
	case 'exp':
155
		/* Exporting a certificate */
156 f0b38e39 jim-p
		send_user_download('data', base64_decode($thiscert['crt']), "{$thiscert['descr']}.crt");
157 7e83055a jim-p
		break;
158
	case 'req':
159
		/* Exporting a certificate signing request */
160 f0b38e39 jim-p
		send_user_download('data', base64_decode($thiscert['csr']), "{$thiscert['descr']}.req");
161 7e83055a jim-p
		break;
162
	case 'key':
163
		/* Exporting a private key */
164 96773352 jim-p
		$keyout = base64_decode($thiscert['prv']);
165
		if (isset($_POST['exportpass']) && !empty($_POST['exportpass'])) {
166 6b44352b Viktor Gurov
			if ((strlen($_POST['exportpass']) < 4) or (strlen($_POST['exportpass']) > 1023)) {
167
				$savemsg = gettext("Export password must be in 4 to 1023 characters.");
168 96773352 jim-p
				$class = 'danger';
169 6b44352b Viktor Gurov
				break;
170
			} else {
171
				$res_key = openssl_pkey_get_private($keyout);
172
				if ($res_key) {
173 8e4ad4c8 Viktor Gurov
					$args = array('encrypt_key_cipher' => OPENSSL_CIPHER_AES_256_CBC);
174
					openssl_pkey_export($res_key, $keyout, $_POST['exportpass'], $args);
175 6b44352b Viktor Gurov
				} else {
176
					$savemsg = gettext("Unable to export password-protected private key.");
177
					$class = 'danger';
178
				}
179 96773352 jim-p
			}
180
		}
181
		if (!empty($keyout)) {
182
			send_user_download('data', $keyout, "{$thiscert['descr']}.key");
183
		}
184 7e83055a jim-p
		break;
185
	case 'p12':
186
		/* Exporting a PKCS#12 file containing the certificate, key, and (if present) CA */
187 28631275 Viktor Gurov
		if (isset($_POST['exportpass']) && !empty($_POST['exportpass'])) {
188 6b44352b Viktor Gurov
			if ((strlen($_POST['exportpass']) < 4) or (strlen($_POST['exportpass']) > 1023)) {
189
				$savemsg = gettext("Export password must be in 4 to 1023 characters.");
190
				$class = 'danger';
191
				break;
192
			} else {
193
				$password = $_POST['exportpass'];
194
			}
195
		} else {
196
			$password = null;
197
		}
198 7e83055a jim-p
		$args = array();
199 f0b38e39 jim-p
		$args['friendly_name'] = $thiscert['descr'];
200 8e4ad4c8 Viktor Gurov
		$args['encrypt_key_cipher'] = OPENSSL_CIPHER_AES_256_CBC;
201 f0b38e39 jim-p
		$ca = lookup_ca($thiscert['caref']);
202 7e83055a jim-p
		if ($ca) {
203
			/* If the CA can be found, then add the CA to the container */
204
			$args['extracerts'] = openssl_x509_read(base64_decode($ca['crt']));
205
		}
206 f0b38e39 jim-p
		$res_crt = openssl_x509_read(base64_decode($thiscert['crt']));
207
		$res_key = openssl_pkey_get_private(base64_decode($thiscert['prv']));
208 7e83055a jim-p
		$exp_data = "";
209 96773352 jim-p
		openssl_pkcs12_export($res_crt, $exp_data, $res_key, $password, $args);
210 f0b38e39 jim-p
		send_user_download('data', $exp_data, "{$thiscert['descr']}.p12");
211 7e83055a jim-p
		break;
212
	default:
213
		break;
214 64cc39d3 Matthew Grooms
}
215
216 7e83055a jim-p
if ($_POST['save'] == gettext("Save")) {
217
	/* Creating a new entry */
218
	$input_errors = array();
219
	$pconfig = $_POST;
220 0edcccc3 Daniel Seebald
221 7e83055a jim-p
	switch ($pconfig['method']) {
222
		case 'sign':
223 2052d3e2 Steve Beaver
			$reqdfields = explode(" ",
224
				"descr catosignwith");
225
			$reqdfieldsn = array(
226
				gettext("Descriptive name"),
227
				gettext("CA to sign with"));
228
229 7db12011 jim-p
			if (($_POST['csrtosign'] === "new") &&
230
			    ((!strstr($_POST['csrpaste'], "BEGIN CERTIFICATE REQUEST") || !strstr($_POST['csrpaste'], "END CERTIFICATE REQUEST")) &&
231
			    (!strstr($_POST['csrpaste'], "BEGIN NEW CERTIFICATE REQUEST") || !strstr($_POST['csrpaste'], "END NEW CERTIFICATE REQUEST")))) {
232 2052d3e2 Steve Beaver
				$input_errors[] = gettext("This signing request does not appear to be valid.");
233
			}
234 55047259 Steve Beaver
235 c13a8a59 Viktor Gurov
			if ( (($_POST['csrtosign'] === "new") && (strlen($_POST['keypaste']) > 0)) && 
236 b1370c94 Viktor Gurov
			    ((!strstr($_POST['keypaste'], "BEGIN PRIVATE KEY") && !strstr($_POST['keypaste'], "BEGIN EC PRIVATE KEY")) || 
237
			    (strstr($_POST['keypaste'], "BEGIN PRIVATE KEY") && !strstr($_POST['keypaste'], "END PRIVATE KEY")) ||
238
			    (strstr($_POST['keypaste'], "BEGIN EC PRIVATE KEY") && !strstr($_POST['keypaste'], "END EC PRIVATE KEY")))) {
239 55047259 Steve Beaver
				$input_errors[] = gettext("This private does not appear to be valid.");
240
				$input_errors[] = gettext("Key data field should be blank, or a valid x509 private key");
241
			}
242 96d78012 Viktor Gurov
243 3a877e4a jim-p
			if ($_POST['lifetime'] > $max_lifetime) {
244
				$input_errors[] = gettext("Lifetime is longer than the maximum allowed value. Use a shorter lifetime.");
245
			}
246 7e83055a jim-p
			break;
247 96773352 jim-p
		case 'edit':
248 7e83055a jim-p
		case 'import':
249 96d78012 Viktor Gurov
			$pkcs12_data = '';
250
			if ($_POST['import_type'] == 'x509') {
251
				$reqdfields = explode(" ",
252
					"descr cert");
253
				$reqdfieldsn = array(
254
					gettext("Descriptive name"),
255
					gettext("Certificate data"));
256
				if ($_POST['cert'] && (!strstr($_POST['cert'], "BEGIN CERTIFICATE") || !strstr($_POST['cert'], "END CERTIFICATE"))) {
257
					$input_errors[] = gettext("This certificate does not appear to be valid.");
258
				}
259 55047259 Steve Beaver
260 96d78012 Viktor Gurov
				if ($_POST['key'] && (cert_get_publickey($_POST['cert'], false) != cert_get_publickey($_POST['key'], false, 'prv'))) {
261
					$input_errors[] = gettext("The submitted private key does not match the submitted certificate data.");
262
				}
263
			} else {
264
				$reqdfields = array('descr');
265
				$reqdfieldsn = array(gettext("Descriptive name"));
266
				if (!empty($_FILES['pkcs12_cert']) && is_uploaded_file($_FILES['pkcs12_cert']['tmp_name'])) {
267
					$pkcs12_file = file_get_contents($_FILES['pkcs12_cert']['tmp_name']);
268
					if (!openssl_pkcs12_read($pkcs12_file, $pkcs12_data, $_POST['pkcs12_pass'])) {
269
						$input_errors[] = gettext("The submitted password does not unlock the submitted PKCS #12 certificate.");
270
					}
271
				} else {
272
					$input_errors[] = gettext("A PKCS #12 certificate store was not uploaded.");
273
				}
274 2cf5db21 jim-p
			}
275 7e83055a jim-p
			break;
276
		case 'internal':
277 64cc39d3 Matthew Grooms
			$reqdfields = explode(" ",
278 ff5bc49c Viktor Gurov
				"descr caref keylen ecname keytype type lifetime dn_commonname");
279 38fb1109 Vinicius Coque
			$reqdfieldsn = array(
280 56b1ed39 Phil Davis
				gettext("Descriptive name"),
281
				gettext("Certificate authority"),
282
				gettext("Key length"),
283 e0f8d364 Viktor Gurov
				gettext("Elliptic Curve Name"),
284 47c46bbd Viktor Gurov
				gettext("Key type"),
285 56b1ed39 Phil Davis
				gettext("Certificate Type"),
286
				gettext("Lifetime"),
287 0c51971b jim-p
				gettext("Common Name"));
288 3a877e4a jim-p
			if ($_POST['lifetime'] > $max_lifetime) {
289
				$input_errors[] = gettext("Lifetime is longer than the maximum allowed value. Use a shorter lifetime.");
290
			}
291 7e83055a jim-p
			break;
292
		case 'external':
293 64cc39d3 Matthew Grooms
			$reqdfields = explode(" ",
294 e0f8d364 Viktor Gurov
				"descr csr_keylen csr_ecname csr_keytype csr_dn_commonname");
295 38fb1109 Vinicius Coque
			$reqdfieldsn = array(
296 56b1ed39 Phil Davis
				gettext("Descriptive name"),
297
				gettext("Key length"),
298 e0f8d364 Viktor Gurov
				gettext("Elliptic Curve Name"),
299 dace81a7 Viktor Gurov
				gettext("Key type"),
300 0c51971b jim-p
				gettext("Common Name"));
301 7e83055a jim-p
			break;
302
		case 'existing':
303 ad9b5c67 jim-p
			$reqdfields = array("certref");
304
			$reqdfieldsn = array(gettext("Existing Certificate Choice"));
305 7e83055a jim-p
			break;
306
		default:
307
			break;
308
	}
309 bf9d50e8 Stephen Beaver
310 7e83055a jim-p
	$altnames = array();
311
	do_input_validation($_POST, $reqdfields, $reqdfieldsn, $input_errors);
312
313 96773352 jim-p
	if (!in_array($pconfig['method'], array('edit', 'import', 'existing'))) {
314 7e83055a jim-p
		/* subjectAltNames */
315
		$san_typevar = 'altname_type';
316
		$san_valuevar = 'altname_value';
317
		// This is just the blank alternate name that is added for display purposes. We don't want to validate/save it
318
		if ($_POST["{$san_valuevar}0"] == "") {
319
			unset($_POST["{$san_typevar}0"]);
320
			unset($_POST["{$san_valuevar}0"]);
321
		}
322
		foreach ($_POST as $key => $value) {
323
			$entry = '';
324
			if (!substr_compare($san_typevar, $key, 0, strlen($san_typevar))) {
325
				$entry = substr($key, strlen($san_typevar));
326
				$field = 'type';
327
			} elseif (!substr_compare($san_valuevar, $key, 0, strlen($san_valuevar))) {
328
				$entry = substr($key, strlen($san_valuevar));
329
				$field = 'value';
330 2f65de89 jim-p
			}
331 bf9d50e8 Stephen Beaver
332 7e83055a jim-p
			if (ctype_digit($entry)) {
333
				$entry++;	// Pre-bootstrap code is one-indexed, but the bootstrap code is 0-indexed
334
				$altnames[$entry][$field] = $value;
335 2f65de89 jim-p
			}
336 7e83055a jim-p
		}
337 2f65de89 jim-p
338 7e83055a jim-p
		$pconfig['altnames']['item'] = $altnames;
339 b741d2ef jim-p
340 7e83055a jim-p
		/* Input validation for subjectAltNames */
341
		foreach ($altnames as $idx => $altname) {
342
			switch ($altname['type']) {
343
				case "DNS":
344
					if (!is_hostname($altname['value'], true) || is_ipaddr($altname['value'])) {
345
						$input_errors[] = gettext("DNS subjectAltName values must be valid hostnames, FQDNs or wildcard domains.");
346 ed76624b jim-p
					}
347
					break;
348 7e83055a jim-p
				case "IP":
349
					if (!is_ipaddr($altname['value'])) {
350
						$input_errors[] = gettext("IP subjectAltName values must be valid IP Addresses");
351 dace81a7 Viktor Gurov
					}
352 7e83055a jim-p
					break;
353
				case "email":
354
					if (empty($altname['value'])) {
355
						$input_errors[] = gettext("An e-mail address must be provided for this type of subjectAltName");
356 dace81a7 Viktor Gurov
					}
357 7e83055a jim-p
					if (preg_match("/[\!\#\$\%\^\(\)\~\?\>\<\&\/\\\,\"\']/", $altname['value'])) {
358
						$input_errors[] = gettext("The e-mail provided in a subjectAltName contains invalid characters.");
359 ed76624b jim-p
					}
360
					break;
361 7e83055a jim-p
				case "URI":
362
					/* Close enough? */
363
					if (!is_URL($altname['value'])) {
364
						$input_errors[] = gettext("URI subjectAltName types must be a valid URI");
365 ed76624b jim-p
					}
366
					break;
367
				default:
368 7e83055a jim-p
					$input_errors[] = gettext("Unrecognized subjectAltName type.");
369 aec3a259 jim-p
			}
370 547c56c4 jim-p
		}
371 64cc39d3 Matthew Grooms
372 7e83055a jim-p
		/* Make sure we do not have invalid characters in the fields for the certificate */
373
		if (preg_match("/[\?\>\<\&\/\\\"\']/", $_POST['descr'])) {
374
			$input_errors[] = gettext("The field 'Descriptive Name' contains invalid characters.");
375
		}
376 64cc39d3 Matthew Grooms
377 7e83055a jim-p
		switch ($pconfig['method']) {
378
			case "internal":
379
				if (isset($_POST["keytype"]) && !in_array($_POST["keytype"], $cert_keytypes)) {
380
					$input_errors[] = gettext("Please select a valid Key Type.");
381 56b1ed39 Phil Davis
				}
382 7e83055a jim-p
				if (isset($_POST["keylen"]) && !in_array($_POST["keylen"], $cert_keylens)) {
383
					$input_errors[] = gettext("Please select a valid Key Length.");
384 2052d3e2 Steve Beaver
				}
385 cffcf9bf jim-p
				if (isset($_POST["ecname"]) && !in_array($_POST["ecname"], array_keys($openssl_ecnames))) {
386 7e83055a jim-p
					$input_errors[] = gettext("Please select a valid Elliptic Curve Name.");
387
				}
388
				if (!in_array($_POST["digest_alg"], $openssl_digest_algs)) {
389
					$input_errors[] = gettext("Please select a valid Digest Algorithm.");
390
				}
391
				break;
392
			case "external":
393
				if (isset($_POST["csr_keytype"]) && !in_array($_POST["csr_keytype"], $cert_keytypes)) {
394
					$input_errors[] = gettext("Please select a valid Key Type.");
395 55047259 Steve Beaver
				}
396 7e83055a jim-p
				if (isset($_POST["csr_keylen"]) && !in_array($_POST["csr_keylen"], $cert_keylens)) {
397
					$input_errors[] = gettext("Please select a valid Key Length.");
398
				}
399 cffcf9bf jim-p
				if (isset($_POST["csr_ecname"]) && !in_array($_POST["csr_ecname"], array_keys($openssl_ecnames))) {
400 7e83055a jim-p
					$input_errors[] = gettext("Please select a valid Elliptic Curve Name.");
401
				}
402
				if (!in_array($_POST["csr_digest_alg"], $openssl_digest_algs)) {
403
					$input_errors[] = gettext("Please select a valid Digest Algorithm.");
404
				}
405
				break;
406
			case "sign":
407
				if (!in_array($_POST["csrsign_digest_alg"], $openssl_digest_algs)) {
408
					$input_errors[] = gettext("Please select a valid Digest Algorithm.");
409
				}
410
				break;
411
			default:
412
				break;
413
		}
414
	}
415 2052d3e2 Steve Beaver
416 7e83055a jim-p
	/* save modifications */
417
	if (!$input_errors) {
418 96773352 jim-p
		$old_err_level = error_reporting(0); /* otherwise openssl_ functions throw warnings directly to a page breaking menu tabs */
419 b078cd59 Steve Beaver
420 96773352 jim-p
		if (isset($id) && $thiscert) {
421
			$cert = $thiscert;
422 7e83055a jim-p
		} else {
423
			$cert = array();
424
			$cert['refid'] = uniqid();
425 96773352 jim-p
		}
426 ad9b5c67 jim-p
427 96773352 jim-p
		$cert['descr'] = $pconfig['descr'];
428 282b6c66 jim-p
429 96773352 jim-p
		switch($pconfig['method']) {
430
			case 'existing':
431
				/* Add an existing certificate to a user */
432
				$ucert = lookup_cert($pconfig['certref']);
433
				if ($ucert && $a_user) {
434
					$a_user[$userid]['cert'][] = $ucert['refid'];
435
					$savemsg = sprintf(gettext("Added certificate %s to user %s"), $ucert['descr'], $a_user[$userid]['name']);
436
				}
437
				unset($cert);
438
				break;
439
			case 'sign':
440
				/* Sign a CSR */
441
				$csrid = lookup_cert($pconfig['csrtosign']);
442
				$ca = & lookup_ca($pconfig['catosignwith']);
443
				// Read the CSR from $config, or if a new one, from the textarea
444
				if ($pconfig['csrtosign'] === "new") {
445
					$csr = $pconfig['csrpaste'];
446
				} else {
447
					$csr = base64_decode($csrid['csr']);
448
				}
449
				if (count($altnames)) {
450
					foreach ($altnames as $altname) {
451
						$altnames_tmp[] = "{$altname['type']}:" . cert_escape_x509_chars($altname['value']);
452
					}
453
					$altname_str = implode(",", $altnames_tmp);
454
				}
455
				$n509 = csr_sign($csr, $ca, $pconfig['csrsign_lifetime'], $pconfig['type'], $altname_str, $pconfig['csrsign_digest_alg']);
456
				if ($n509) {
457
					// Gather the details required to save the new cert
458
					$newcert = array();
459
					$newcert['refid'] = uniqid();
460
					$newcert['caref'] = $pconfig['catosignwith'];
461
					$newcert['descr'] = $pconfig['descr'];
462
					$newcert['type'] = $pconfig['type'];
463
					$newcert['crt'] = base64_encode($n509);
464
					if ($pconfig['csrtosign'] === "new") {
465
						$newcert['prv'] = base64_encode($pconfig['keypaste']);
466
					} else {
467
						$newcert['prv'] = $csrid['prv'];
468
					}
469
					// Add it to the config file
470
					$config['cert'][] = $newcert;
471
					$savemsg = sprintf(gettext("Signed certificate %s"), $newcert['descr']);
472
				}
473
				unset($cert);
474
				break;
475
			case 'edit':
476
				cert_import($cert, $pconfig['cert'], $pconfig['key']);
477
				$savemsg = sprintf(gettext("Edited certificate %s"), $cert['descr']);
478
				break;
479
			case 'import':
480
				/* Import an external certificate+key */
481 96d78012 Viktor Gurov
				if ($pkcs12_data) {
482
					$pconfig['cert'] = $pkcs12_data['cert'];
483
					$pconfig['key'] = $pkcs12_data['pkey'];
484
					if ($_POST['pkcs12_intermediate'] && is_array($pkcs12_data['extracerts'])) {
485
						foreach ($pkcs12_data['extracerts'] as $intermediate) {
486
							$int_data = openssl_x509_parse($intermediate);
487
							if (!$int_data) continue;
488
							$cn = $int_data['subject']['CN'];
489
							$int_ca = array('descr' => $cn, 'refid' => uniqid());
490
							if (ca_import($int_ca, $intermediate)) {
491
								$a_ca[] = $int_ca;
492
							}
493
						}
494
					}
495
				}
496 7e83055a jim-p
				cert_import($cert, $pconfig['cert'], $pconfig['key']);
497 f0b38e39 jim-p
				$savemsg = sprintf(gettext("Imported certificate %s"), $cert['descr']);
498 96773352 jim-p
				break;
499
			case 'internal':
500
				/* Create an internal certificate */
501 7e83055a jim-p
				$dn = array('commonName' => cert_escape_x509_chars($pconfig['dn_commonname']));
502
				if (!empty($pconfig['dn_country'])) {
503
					$dn['countryName'] = $pconfig['dn_country'];
504
				}
505
				if (!empty($pconfig['dn_state'])) {
506
					$dn['stateOrProvinceName'] = cert_escape_x509_chars($pconfig['dn_state']);
507
				}
508
				if (!empty($pconfig['dn_city'])) {
509
					$dn['localityName'] = cert_escape_x509_chars($pconfig['dn_city']);
510
				}
511
				if (!empty($pconfig['dn_organization'])) {
512
					$dn['organizationName'] = cert_escape_x509_chars($pconfig['dn_organization']);
513
				}
514
				if (!empty($pconfig['dn_organizationalunit'])) {
515
					$dn['organizationalUnitName'] = cert_escape_x509_chars($pconfig['dn_organizationalunit']);
516
				}
517
				$altnames_tmp = array();
518
				$cn_altname = cert_add_altname_type($pconfig['dn_commonname']);
519
				if (!empty($cn_altname)) {
520
					$altnames_tmp[] = $cn_altname;
521
				}
522
				if (count($altnames)) {
523
					foreach ($altnames as $altname) {
524
						// The CN is added as a SAN automatically, do not add it again.
525
						if ($altname['value'] != $pconfig['dn_commonname']) {
526
							$altnames_tmp[] = "{$altname['type']}:" . cert_escape_x509_chars($altname['value']);
527 2f65de89 jim-p
						}
528 282b6c66 jim-p
					}
529 7e83055a jim-p
				}
530
				if (!empty($altnames_tmp)) {
531
					$dn['subjectAltName'] = implode(",", $altnames_tmp);
532
				}
533
				if (!cert_create($cert, $pconfig['caref'], $pconfig['keylen'], $pconfig['lifetime'], $dn, $pconfig['type'], $pconfig['digest_alg'], $pconfig['keytype'], $pconfig['ecname'])) {
534
					$input_errors = array();
535
					while ($ssl_err = openssl_error_string()) {
536
						if (strpos($ssl_err, 'NCONF_get_string:no value') === false) {
537
							$input_errors[] = sprintf(gettext("OpenSSL Library Error: %s"), $ssl_err);
538 22b380aa Evgeny Yurchenko
						}
539
					}
540 ad9b5c67 jim-p
				}
541 f0b38e39 jim-p
				$savemsg = sprintf(gettext("Created internal certificate %s"), $cert['descr']);
542 96773352 jim-p
				break;
543
			case 'external':
544
				/* Create a certificate signing request */
545 7e83055a jim-p
				$dn = array('commonName' => cert_escape_x509_chars($pconfig['csr_dn_commonname']));
546
				if (!empty($pconfig['csr_dn_country'])) {
547
					$dn['countryName'] = $pconfig['csr_dn_country'];
548
				}
549
				if (!empty($pconfig['csr_dn_state'])) {
550
					$dn['stateOrProvinceName'] = cert_escape_x509_chars($pconfig['csr_dn_state']);
551
				}
552
				if (!empty($pconfig['csr_dn_city'])) {
553
					$dn['localityName'] = cert_escape_x509_chars($pconfig['csr_dn_city']);
554
				}
555
				if (!empty($pconfig['csr_dn_organization'])) {
556
					$dn['organizationName'] = cert_escape_x509_chars($pconfig['csr_dn_organization']);
557
				}
558
				if (!empty($pconfig['csr_dn_organizationalunit'])) {
559
					$dn['organizationalUnitName'] = cert_escape_x509_chars($pconfig['csr_dn_organizationalunit']);
560
				}
561
				$altnames_tmp = array();
562
				$cn_altname = cert_add_altname_type($pconfig['csr_dn_commonname']);
563
				if (!empty($cn_altname)) {
564
					$altnames_tmp[] = $cn_altname;
565
				}
566
				if (count($altnames)) {
567
					foreach ($altnames as $altname) {
568
						// The CN is added as a SAN automatically, do not add it again.
569
						if ($altname['value'] != $pconfig['csr_dn_commonname']) {
570
							$altnames_tmp[] = "{$altname['type']}:" . cert_escape_x509_chars($altname['value']);
571
						}
572
					}
573
				}
574
				if (!empty($altnames_tmp)) {
575
					$dn['subjectAltName'] = implode(",", $altnames_tmp);
576 56b1ed39 Phil Davis
				}
577 7e83055a jim-p
				if (!csr_generate($cert, $pconfig['csr_keylen'], $dn, $pconfig['type'], $pconfig['csr_digest_alg'], $pconfig['csr_keytype'], $pconfig['csr_ecname'])) {
578
					$input_errors = array();
579
					while ($ssl_err = openssl_error_string()) {
580
						if (strpos($ssl_err, 'NCONF_get_string:no value') === false) {
581
							$input_errors[] = sprintf(gettext("OpenSSL Library Error: %s"), $ssl_err);
582
						}
583
					}
584 56b1ed39 Phil Davis
				}
585 f0b38e39 jim-p
				$savemsg = sprintf(gettext("Created certificate signing request %s"), $cert['descr']);
586 96773352 jim-p
				break;
587
			default:
588
				break;
589
		}
590
		error_reporting($old_err_level);
591 7e83055a jim-p
592 96773352 jim-p
		if (isset($id) && $thiscert) {
593
			$thiscert = $cert;
594
		} elseif ($cert) {
595
			$a_cert[] = $cert;
596
		}
597 64cc39d3 Matthew Grooms
598 96773352 jim-p
		if (isset($a_user) && isset($userid)) {
599
			$a_user[$userid]['cert'][] = $cert['refid'];
600 64cc39d3 Matthew Grooms
		}
601
602 7e83055a jim-p
		if (!$input_errors) {
603 f0b38e39 jim-p
			write_config($savemsg);
604 b741d2ef jim-p
		}
605
606 7e83055a jim-p
		if ((isset($userid) && is_numeric($userid)) && !$input_errors) {
607
			post_redirect("system_usermanager.php", array('act' => 'edit', 'userid' => $userid));
608
			exit;
609 a828210b yakatz
		}
610 7e83055a jim-p
	}
611
} elseif ($_POST['save'] == gettext("Update")) {
612
	/* Updating a certificate signing request */
613
	unset($input_errors);
614
	$pconfig = $_POST;
615 64cc39d3 Matthew Grooms
616 7e83055a jim-p
	/* input validation */
617
	$reqdfields = explode(" ", "descr cert");
618
	$reqdfieldsn = array(
619
		gettext("Descriptive name"),
620
		gettext("Final Certificate data"));
621 64cc39d3 Matthew Grooms
622 7e83055a jim-p
	do_input_validation($_POST, $reqdfields, $reqdfieldsn, $input_errors);
623 64cc39d3 Matthew Grooms
624 7e83055a jim-p
	if (preg_match("/[\?\>\<\&\/\\\"\']/", $_POST['descr'])) {
625
		$input_errors[] = gettext("The field 'Descriptive Name' contains invalid characters.");
626
	}
627 64cc39d3 Matthew Grooms
628 7e83055a jim-p
	$mod_csr = cert_get_publickey($pconfig['csr'], false, 'csr');
629
	$mod_cert = cert_get_publickey($pconfig['cert'], false);
630 64cc39d3 Matthew Grooms
631 7e83055a jim-p
	if (strcmp($mod_csr, $mod_cert)) {
632
		// simply: if the moduli don't match, then the private key and public key won't match
633
		$input_errors[] = gettext("The certificate public key does not match the signing request public key.");
634
		$subject_mismatch = true;
635
	}
636 64cc39d3 Matthew Grooms
637 7e83055a jim-p
	/* save modifications */
638
	if (!$input_errors) {
639 f0b38e39 jim-p
		$cert = $thiscert;
640 7e83055a jim-p
		$cert['descr'] = $pconfig['descr'];
641
		csr_complete($cert, $pconfig['cert']);
642 f0b38e39 jim-p
		$thiscert = $cert;
643
		$savemsg = sprintf(gettext("Updated certificate signing request %s"), $pconfig['descr']);
644
		write_config($savemsg);
645 7e83055a jim-p
		pfSenseHeader("system_certmanager.php");
646 64cc39d3 Matthew Grooms
	}
647
}
648
649 56c6b1cb k-paulius
$pgtitle = array(gettext("System"), gettext("Certificate Manager"), gettext("Certificates"));
650 edcd7535 Phil Davis
$pglinks = array("", "system_camanager.php", "system_certmanager.php");
651 56c6b1cb k-paulius
652 7e83055a jim-p
if (($act == "new" || ($_POST['save'] == gettext("Save") && $input_errors)) ||
653
    ($act == "csr" || ($_POST['save'] == gettext("Update") && $input_errors))) {
654 56c6b1cb k-paulius
	$pgtitle[] = gettext('Edit');
655 edcd7535 Phil Davis
	$pglinks[] = "@self";
656 56c6b1cb k-paulius
}
657 64cc39d3 Matthew Grooms
include("head.inc");
658 b49f31d0 Sjon Hortensius
659 78863416 Phil Davis
if ($input_errors) {
660 b49f31d0 Sjon Hortensius
	print_input_errors($input_errors);
661 78863416 Phil Davis
}
662 0edcccc3 Daniel Seebald
663 78863416 Phil Davis
if ($savemsg) {
664 f0b38e39 jim-p
	print_info_box($savemsg, $class);
665 78863416 Phil Davis
}
666 b49f31d0 Sjon Hortensius
667
$tab_array = array();
668
$tab_array[] = array(gettext("CAs"), false, "system_camanager.php");
669
$tab_array[] = array(gettext("Certificates"), true, "system_certmanager.php");
670
$tab_array[] = array(gettext("Certificate Revocation"), false, "system_crlmanager.php");
671
display_top_tabs($tab_array);
672
673 96773352 jim-p
if (in_array($act, array('new', 'edit')) || (($_POST['save'] == gettext("Save")) && $input_errors)) {
674 b35250d9 NewEraCracker
	$form = new Form();
675 96d78012 Viktor Gurov
	$form->setAction('system_certmanager.php')->setMultipartEncoding();
676 b49f31d0 Sjon Hortensius
677 b35250d9 NewEraCracker
	if (isset($userid) && $a_user) {
678
		$form->addGlobal(new Form_Input(
679
			'userid',
680
			null,
681
			'hidden',
682
			$userid
683
		));
684
	}
685 b49f31d0 Sjon Hortensius
686 f0b38e39 jim-p
	if (isset($id) && $thiscert) {
687 b49f31d0 Sjon Hortensius
		$form->addGlobal(new Form_Input(
688
			'id',
689
			null,
690
			'hidden',
691
			$id
692
		));
693 64cc39d3 Matthew Grooms
	}
694 b49f31d0 Sjon Hortensius
695 96773352 jim-p
	switch ($act) {
696
		case 'edit':
697
			$maintitle = gettext('Edit an Existing Certificate');
698
			break;
699
		case 'new':
700
		default:
701
			$maintitle = gettext('Add/Sign a New Certificate');
702
			break;
703
	}
704
705
	$section = new Form_Section($maintitle);
706 b35250d9 NewEraCracker
707 96773352 jim-p
	if (!isset($id) || ($act == 'edit')) {
708 b35250d9 NewEraCracker
		$section->addInput(new Form_Select(
709
			'method',
710 153c3aa6 Phil Davis
			'*Method',
711 b35250d9 NewEraCracker
			$pconfig['method'],
712
			$cert_methods
713
		))->toggles();
714
	}
715
716 b49f31d0 Sjon Hortensius
	$section->addInput(new Form_Input(
717
		'descr',
718 153c3aa6 Phil Davis
		'*Descriptive name',
719 b49f31d0 Sjon Hortensius
		'text',
720 b35250d9 NewEraCracker
		($a_user && empty($pconfig['descr'])) ? $a_user[$userid]['name'] : $pconfig['descr']
721 96773352 jim-p
	))->addClass('toggle-internal toggle-import toggle-edit toggle-external toggle-sign toggle-existing collapse');
722
723
	if (!empty($pconfig['cert'])) {
724
		$section->addInput(new Form_StaticText(
725
			"Subject",
726
			htmlspecialchars(cert_get_subject($pconfig['cert'], false))
727
		))->addClass('toggle-edit collapse');
728
	}
729 b49f31d0 Sjon Hortensius
730 b35250d9 NewEraCracker
	$form->add($section);
731 2052d3e2 Steve Beaver
732 d520da31 Steve Beaver
	// Return an array containing the IDs od all CAs
733 2052d3e2 Steve Beaver
	function list_cas() {
734
		global $a_ca;
735
		$allCas = array();
736
737
		foreach ($a_ca as $ca) {
738
			if ($ca['prv']) {
739 d520da31 Steve Beaver
				$allCas[$ca['refid']] = $ca['descr'];
740 2052d3e2 Steve Beaver
			}
741
		}
742
743
		return $allCas;
744
	}
745
746 d520da31 Steve Beaver
	// Return an array containing the IDs od all CSRs
747 2052d3e2 Steve Beaver
	function list_csrs() {
748
		global $config;
749
		$allCsrs = array();
750
751
		foreach ($config['cert'] as $cert) {
752
			if ($cert['csr']) {
753 d520da31 Steve Beaver
				$allCsrs[$cert['refid']] = $cert['descr'];
754 2052d3e2 Steve Beaver
			}
755
		}
756
757 d6107e1a Steve Beaver
		return ['new' => gettext('New CSR (Paste below)')] + $allCsrs;
758 2052d3e2 Steve Beaver
	}
759
760
	$section = new Form_Section('Sign CSR');
761
	$section->addClass('toggle-sign collapse');
762
763
	$section->AddInput(new Form_Select(
764
		'catosignwith',
765
		'*CA to sign with',
766
		$pconfig['catosignwith'],
767
		list_cas()
768
	));
769
770
	$section->AddInput(new Form_Select(
771
		'csrtosign',
772
		'*CSR to sign',
773
		isset($pconfig['csrtosign']) ? $pconfig['csrtosign'] : 'new',
774
		list_csrs()
775
	));
776
777
	$section->addInput(new Form_Textarea(
778
		'csrpaste',
779
		'CSR data',
780
		$pconfig['csrpaste']
781
	))->setHelp('Paste a Certificate Signing Request in X.509 PEM format here.');
782
783 55047259 Steve Beaver
	$section->addInput(new Form_Textarea(
784
		'keypaste',
785
		'Key data',
786
		$pconfig['keypaste']
787 c67c74dd Steve Beaver
	))->setHelp('Optionally paste a private key here. The key will be associated with the newly signed certificate in %1$s', $g['product_label']);
788 55047259 Steve Beaver
789 0c82b8c2 jim-p
	$section->addInput(new Form_Input(
790
		'csrsign_lifetime',
791
		'*Certificate Lifetime (days)',
792
		'number',
793 3a877e4a jim-p
		$pconfig['csrsign_lifetime'] ? $pconfig['csrsign_lifetime']:$default_lifetime,
794
		['max' => $max_lifetime]
795 3f0b7bc3 jim-p
	))->setHelp('The length of time the signed certificate will be valid, in days. %1$s' .
796 f944f4a7 jim-p
		'Server certificates should not have a lifetime over %2$s days or some platforms ' .
797
		'may consider the certificate invalid.', '<br/>', $cert_strict_values['max_server_cert_lifetime']);
798 aec3a259 jim-p
	$section->addInput(new Form_Select(
799
		'csrsign_digest_alg',
800
		'*Digest Algorithm',
801
		$pconfig['csrsign_digest_alg'],
802
		array_combine($openssl_digest_algs, $openssl_digest_algs)
803 3f0b7bc3 jim-p
	))->setHelp('The digest method used when the certificate is signed. %1$s' .
804
		'The best practice is to use an algorithm stronger than SHA1. '.
805
		'Some platforms may consider weaker digest algorithms invalid', '<br/>');
806 0c82b8c2 jim-p
807 2052d3e2 Steve Beaver
	$form->add($section);
808
809 96773352 jim-p
	if ($act == 'edit') {
810
		$editimport = gettext("Edit Certificate");
811
	} else {
812
		$editimport = gettext("Import Certificate");
813
	}
814
815
	$section = new Form_Section($editimport);
816
	$section->addClass('toggle-import toggle-edit collapse');
817 b49f31d0 Sjon Hortensius
818 96d78012 Viktor Gurov
	$group = new Form_Group('Certificate Type');
819
820
	$group->add(new Form_Checkbox(
821
		'import_type',
822
		'Certificate Type',
823
		'X.509 (PEM)',
824
		(!isset($pconfig['import_type']) || $pconfig['import_type'] == 'x509'),
825
		'x509'
826
	))->displayAsRadio()->addClass('import_type_toggle');
827
828
	$group->add(new Form_Checkbox(
829
		'import_type',
830
		'Certificate Type',
831
		'PKCS #12 (PFX)',
832
		(isset($pconfig['import_type']) && $pconfig['import_type'] == 'pkcs12'),
833
		'pkcs12'
834
	))->displayAsRadio()->addClass('import_type_toggle');
835
836
	$section->add($group);
837
838 b49f31d0 Sjon Hortensius
	$section->addInput(new Form_Textarea(
839
		'cert',
840 153c3aa6 Phil Davis
		'*Certificate data',
841 78863416 Phil Davis
		$pconfig['cert']
842 b35250d9 NewEraCracker
	))->setHelp('Paste a certificate in X.509 PEM format here.');
843
844
	$section->addInput(new Form_Textarea(
845
		'key',
846 8c145373 Viktor G
		'Private key data',
847 b35250d9 NewEraCracker
		$pconfig['key']
848 8c145373 Viktor G
	))->setHelp('Paste a private key in X.509 PEM format here. This field may remain empty in certain cases, such as when the private key is stored on a PKCS#11 token.');
849 b49f31d0 Sjon Hortensius
850 96d78012 Viktor Gurov
	$section->addInput(new Form_Input(
851
		'pkcs12_cert',
852
		'PKCS #12 certificate',
853
		'file',
854
		$pconfig['pkcs12_cert']
855
	))->setHelp('Select a PKCS #12 certificate store.');
856
857
	$section->addInput(new Form_Input(
858
		'pkcs12_pass',
859
		'PKCS #12 certificate password',
860
		'password',
861
		$pconfig['pkcs12_pass']
862
	))->setHelp('Enter the password to unlock the PKCS #12 certificate store.');
863
864
	$section->addInput(new Form_Checkbox(
865
		'pkcs12_intermediate',
866
		'Intermediates',
867
		'Import intermediate CAs',
868
		isset($pconfig['pkcs12_intermediate'])
869
	))->setHelp('Import any intermediate certificate authorities found in the PKCS #12 certificate store.');
870
871 67b49e4c Viktor G
	if ($act == 'edit') {
872
		$section->addInput(new Form_Input(
873
			'exportpass',
874
			'Export Password',
875
			'password',
876
			null,
877
			['placeholder' => gettext('Export Password'), 'autocomplete' => 'new-password']
878
		))->setHelp('Enter the password to use when using the export buttons below (not stored)')->addClass('toggle-edit collapse');
879
	}
880 96773352 jim-p
881 b49f31d0 Sjon Hortensius
	$form->add($section);
882 b35250d9 NewEraCracker
	$section = new Form_Section('Internal Certificate');
883
	$section->addClass('toggle-internal collapse');
884
885
	if (!$internal_ca_count) {
886
		$section->addInput(new Form_StaticText(
887 153c3aa6 Phil Davis
			'*Certificate authority',
888 781d9ce4 Phil Davis
			gettext('No internal Certificate Authorities have been defined. ') .
889
			gettext('An internal CA must be defined in order to create an internal certificate. ') .
890
			sprintf(gettext('%1$sCreate%2$s an internal CA.'), '<a href="system_camanager.php?act=new&amp;method=internal"> ', '</a>')
891 b35250d9 NewEraCracker
		));
892
	} else {
893
		$allCas = array();
894
		foreach ($a_ca as $ca) {
895
			if (!$ca['prv']) {
896
				continue;
897
			}
898 b49f31d0 Sjon Hortensius
899 b35250d9 NewEraCracker
			$allCas[ $ca['refid'] ] = $ca['descr'];
900
		}
901 64cc39d3 Matthew Grooms
902 b35250d9 NewEraCracker
		$section->addInput(new Form_Select(
903
			'caref',
904 153c3aa6 Phil Davis
			'*Certificate authority',
905 b35250d9 NewEraCracker
			$pconfig['caref'],
906
			$allCas
907
		));
908
	}
909 64cc39d3 Matthew Grooms
910 b35250d9 NewEraCracker
	$section->addInput(new Form_Select(
911 47c46bbd Viktor Gurov
		'keytype',
912
		'*Key type',
913
		$pconfig['keytype'],
914
		array_combine($cert_keytypes, $cert_keytypes)
915
	));
916
917 dace81a7 Viktor Gurov
	$group = new Form_Group($i == 0 ? '*Key length':'');
918 e0f8d364 Viktor Gurov
	$group->addClass('rsakeys');
919 dace81a7 Viktor Gurov
	$group->add(new Form_Select(
920 b35250d9 NewEraCracker
		'keylen',
921 dace81a7 Viktor Gurov
		null,
922 b35250d9 NewEraCracker
		$pconfig['keylen'],
923
		array_combine($cert_keylens, $cert_keylens)
924 3f0b7bc3 jim-p
	))->setHelp('The length to use when generating a new RSA key, in bits. %1$s' .
925
		'The Key Length should not be lower than 2048 or some platforms ' .
926
		'may consider the certificate invalid.', '<br/>');
927 dace81a7 Viktor Gurov
	$section->add($group);
928
929 e0f8d364 Viktor Gurov
	$group = new Form_Group($i == 0 ? '*Elliptic Curve Name':'');
930 2d13c7fc Viktor Gurov
	$group->addClass('ecnames');
931 dace81a7 Viktor Gurov
	$group->add(new Form_Select(
932 e0f8d364 Viktor Gurov
		'ecname',
933 dace81a7 Viktor Gurov
		null,
934 e0f8d364 Viktor Gurov
		$pconfig['ecname'],
935 cffcf9bf jim-p
		$openssl_ecnames
936
	))->setHelp('Curves may not be compatible with all uses. Known compatible curve uses are denoted in brackets.');
937 dace81a7 Viktor Gurov
	$section->add($group);
938 64cc39d3 Matthew Grooms
939 b35250d9 NewEraCracker
	$section->addInput(new Form_Select(
940
		'digest_alg',
941 153c3aa6 Phil Davis
		'*Digest Algorithm',
942 b35250d9 NewEraCracker
		$pconfig['digest_alg'],
943
		array_combine($openssl_digest_algs, $openssl_digest_algs)
944 3f0b7bc3 jim-p
	))->setHelp('The digest method used when the certificate is signed. %1$s' .
945
		'The best practice is to use an algorithm stronger than SHA1. '.
946
		'Some platforms may consider weaker digest algorithms invalid', '<br/>');
947 b49f31d0 Sjon Hortensius
948 b35250d9 NewEraCracker
	$section->addInput(new Form_Input(
949
		'lifetime',
950 153c3aa6 Phil Davis
		'*Lifetime (days)',
951 b35250d9 NewEraCracker
		'number',
952 3a877e4a jim-p
		$pconfig['lifetime'],
953
		['max' => $max_lifetime]
954 3f0b7bc3 jim-p
	))->setHelp('The length of time the signed certificate will be valid, in days. %1$s' .
955 f944f4a7 jim-p
		'Server certificates should not have a lifetime over %2$s days or some platforms ' .
956
		'may consider the certificate invalid.', '<br/>', $cert_strict_values['max_server_cert_lifetime']);
957 b49f31d0 Sjon Hortensius
958 26e3967a jim-p
	$section->addInput(new Form_Input(
959
		'dn_commonname',
960
		'*Common Name',
961
		'text',
962
		$pconfig['dn_commonname'],
963
		['placeholder' => 'e.g. www.example.com']
964
	));
965
966
	$section->addInput(new Form_StaticText(
967
		null,
968
		gettext('The following certificate subject components are optional and may be left blank.')
969
	));
970
971 b49f31d0 Sjon Hortensius
	$section->addInput(new Form_Select(
972 b35250d9 NewEraCracker
		'dn_country',
973 80d50253 jim-p
		'Country Code',
974 b35250d9 NewEraCracker
		$pconfig['dn_country'],
975 232b1a69 Renato Botelho
		get_cert_country_codes()
976 b49f31d0 Sjon Hortensius
	));
977
978 b35250d9 NewEraCracker
	$section->addInput(new Form_Input(
979
		'dn_state',
980 80d50253 jim-p
		'State or Province',
981 b35250d9 NewEraCracker
		'text',
982
		$pconfig['dn_state'],
983
		['placeholder' => 'e.g. Texas']
984 b49f31d0 Sjon Hortensius
	));
985
986 b35250d9 NewEraCracker
	$section->addInput(new Form_Input(
987
		'dn_city',
988 80d50253 jim-p
		'City',
989 b35250d9 NewEraCracker
		'text',
990
		$pconfig['dn_city'],
991
		['placeholder' => 'e.g. Austin']
992
	));
993
994
	$section->addInput(new Form_Input(
995
		'dn_organization',
996 80d50253 jim-p
		'Organization',
997 b35250d9 NewEraCracker
		'text',
998
		$pconfig['dn_organization'],
999 da0f70ed jim-p
		['placeholder' => 'e.g. My Company Inc']
1000
	));
1001
1002
	$section->addInput(new Form_Input(
1003
		'dn_organizationalunit',
1004
		'Organizational Unit',
1005
		'text',
1006
		$pconfig['dn_organizationalunit'],
1007
		['placeholder' => 'e.g. My Department Name (optional)']
1008 b35250d9 NewEraCracker
	));
1009
1010
	$form->add($section);
1011
	$section = new Form_Section('External Signing Request');
1012
	$section->addClass('toggle-external collapse');
1013
1014 b49f31d0 Sjon Hortensius
	$section->addInput(new Form_Select(
1015 47c46bbd Viktor Gurov
		'csr_keytype',
1016
		'*Key type',
1017
		$pconfig['csr_keytype'],
1018
		array_combine($cert_keytypes, $cert_keytypes)
1019
	));
1020
1021 dace81a7 Viktor Gurov
	$group = new Form_Group($i == 0 ? '*Key length':'');
1022 e0f8d364 Viktor Gurov
	$group->addClass('csr_rsakeys');
1023 dace81a7 Viktor Gurov
	$group->add(new Form_Select(
1024 b35250d9 NewEraCracker
		'csr_keylen',
1025 dace81a7 Viktor Gurov
		null,
1026 b35250d9 NewEraCracker
		$pconfig['csr_keylen'],
1027
		array_combine($cert_keylens, $cert_keylens)
1028 3f0b7bc3 jim-p
	))->setHelp('The length to use when generating a new RSA key, in bits. %1$s' .
1029
		'The Key Length should not be lower than 2048 or some platforms ' .
1030
		'may consider the certificate invalid.', '<br/>');
1031 dace81a7 Viktor Gurov
	$section->add($group);
1032
1033 e0f8d364 Viktor Gurov
	$group = new Form_Group($i == 0 ? '*Elliptic Curve Name':'');
1034 2d13c7fc Viktor Gurov
	$group->addClass('csr_ecnames');
1035 dace81a7 Viktor Gurov
	$group->add(new Form_Select(
1036 e0f8d364 Viktor Gurov
		'csr_ecname',
1037 dace81a7 Viktor Gurov
		null,
1038 e0f8d364 Viktor Gurov
		$pconfig['csr_ecname'],
1039 cffcf9bf jim-p
		$openssl_ecnames
1040 dace81a7 Viktor Gurov
	));
1041
	$section->add($group);
1042 64cc39d3 Matthew Grooms
1043 b35250d9 NewEraCracker
	$section->addInput(new Form_Select(
1044
		'csr_digest_alg',
1045 153c3aa6 Phil Davis
		'*Digest Algorithm',
1046 b35250d9 NewEraCracker
		$pconfig['csr_digest_alg'],
1047
		array_combine($openssl_digest_algs, $openssl_digest_algs)
1048 3f0b7bc3 jim-p
	))->setHelp('The digest method used when the certificate is signed. %1$s' .
1049
		'The best practice is to use an algorithm stronger than SHA1. '.
1050
		'Some platforms may consider weaker digest algorithms invalid', '<br/>');
1051 b49f31d0 Sjon Hortensius
1052 26e3967a jim-p
	$section->addInput(new Form_Input(
1053
		'csr_dn_commonname',
1054
		'*Common Name',
1055
		'text',
1056
		$pconfig['csr_dn_commonname'],
1057
		['placeholder' => 'e.g. internal-ca']
1058
	));
1059
1060
	$section->addInput(new Form_StaticText(
1061
		null,
1062
		gettext('The following certificate subject components are optional and may be left blank.')
1063
	));
1064
1065 b35250d9 NewEraCracker
	$section->addInput(new Form_Select(
1066
		'csr_dn_country',
1067 80d50253 jim-p
		'Country Code',
1068 b35250d9 NewEraCracker
		$pconfig['csr_dn_country'],
1069 232b1a69 Renato Botelho
		get_cert_country_codes()
1070 b35250d9 NewEraCracker
	));
1071 bf9d50e8 Stephen Beaver
1072 b35250d9 NewEraCracker
	$section->addInput(new Form_Input(
1073
		'csr_dn_state',
1074 80d50253 jim-p
		'State or Province',
1075 b35250d9 NewEraCracker
		'text',
1076
		$pconfig['csr_dn_state'],
1077
		['placeholder' => 'e.g. Texas']
1078
	));
1079 bf9d50e8 Stephen Beaver
1080 b35250d9 NewEraCracker
	$section->addInput(new Form_Input(
1081
		'csr_dn_city',
1082 80d50253 jim-p
		'City',
1083 b35250d9 NewEraCracker
		'text',
1084
		$pconfig['csr_dn_city'],
1085
		['placeholder' => 'e.g. Austin']
1086
	));
1087 bf9d50e8 Stephen Beaver
1088 b35250d9 NewEraCracker
	$section->addInput(new Form_Input(
1089
		'csr_dn_organization',
1090 80d50253 jim-p
		'Organization',
1091 b35250d9 NewEraCracker
		'text',
1092
		$pconfig['csr_dn_organization'],
1093 da0f70ed jim-p
		['placeholder' => 'e.g. My Company Inc']
1094
	));
1095
1096
	$section->addInput(new Form_Input(
1097
		'csr_dn_organizationalunit',
1098
		'Organizational Unit',
1099
		'text',
1100
		$pconfig['csr_dn_organizationalunit'],
1101
		['placeholder' => 'e.g. My Department Name (optional)']
1102 b35250d9 NewEraCracker
	));
1103 b49f31d0 Sjon Hortensius
1104 0c82b8c2 jim-p
	$form->add($section);
1105
	$section = new Form_Section('Choose an Existing Certificate');
1106
	$section->addClass('toggle-existing collapse');
1107
1108
	$existCerts = array();
1109
1110 ca4456b9 jim-p
	foreach ($config['cert'] as $cert) {
1111
		if (!is_array($cert) || empty($cert)) {
1112
			continue;
1113
		}
1114 0c82b8c2 jim-p
		if (is_array($config['system']['user'][$userid]['cert'])) { // Could be MIA!
1115
			if (isset($userid) && in_array($cert['refid'], $config['system']['user'][$userid]['cert'])) {
1116
				continue;
1117
			}
1118
		}
1119
1120
		$ca = lookup_ca($cert['caref']);
1121
		if ($ca) {
1122
			$cert['descr'] .= " (CA: {$ca['descr']})";
1123
		}
1124
1125
		if (cert_in_use($cert['refid'])) {
1126
			$cert['descr'] .= " (In Use)";
1127
		}
1128
		if (is_cert_revoked($cert)) {
1129
			$cert['descr'] .= " (Revoked)";
1130
		}
1131
1132
		$existCerts[ $cert['refid'] ] = $cert['descr'];
1133
	}
1134
1135
	$section->addInput(new Form_Select(
1136
		'certref',
1137
		'*Existing Certificates',
1138
		$pconfig['certref'],
1139
		$existCerts
1140
	));
1141
1142
	$form->add($section);
1143
1144
	$section = new Form_Section('Certificate Attributes');
1145
	$section->addClass('toggle-external toggle-internal toggle-sign collapse');
1146
1147
	$section->addInput(new Form_StaticText(
1148
		gettext('Attribute Notes'),
1149
		'<span class="help-block">'.
1150
		gettext('The following attributes are added to certificates and ' .
1151
		'requests when they are created or signed. These attributes behave ' .
1152
		'differently depending on the selected mode.') .
1153
		'<br/><br/>' .
1154
		'<span class="toggle-internal collapse">' . gettext('For Internal Certificates, these attributes are added directly to the certificate as shown.') . '</span>' .
1155
		'<span class="toggle-external collapse">' .
1156
		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. ') .
1157
		'<br/><br/>' .
1158
		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>' .
1159
		'<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>' .
1160
		'</span>'
1161
	));
1162
1163
	$section->addInput(new Form_Select(
1164
		'type',
1165
		'*Certificate Type',
1166
		$pconfig['type'],
1167
		$cert_types
1168
	))->setHelp('Add type-specific usage attributes to the signed certificate.' .
1169
		' Used for placing usage restrictions on, or granting abilities to, ' .
1170
		'the signed certificate.');
1171
1172 282b6c66 jim-p
	if (empty($pconfig['altnames']['item'])) {
1173
		$pconfig['altnames']['item'] = array(
1174
			array('type' => null, 'value' => null)
1175
		);
1176
	}
1177
1178
	$counter = 0;
1179
	$numrows = count($pconfig['altnames']['item']) - 1;
1180
1181
	foreach ($pconfig['altnames']['item'] as $item) {
1182
1183
		$group = new Form_Group($counter == 0 ? 'Alternative Names':'');
1184
1185
		$group->add(new Form_Select(
1186
			'altname_type' . $counter,
1187
			'Type',
1188
			$item['type'],
1189
			$cert_altname_types
1190
		))->setHelp(($counter == $numrows) ? 'Type':null);
1191
1192
		$group->add(new Form_Input(
1193
			'altname_value' . $counter,
1194
			null,
1195
			'text',
1196
			$item['value']
1197
		))->setHelp(($counter == $numrows) ? 'Value':null);
1198
1199
		$group->add(new Form_Button(
1200
			'deleterow' . $counter,
1201
			'Delete',
1202
			null,
1203
			'fa-trash'
1204
		))->addClass('btn-warning');
1205
1206
		$group->addClass('repeatable');
1207
1208 0c82b8c2 jim-p
		$group->setHelp('Enter additional identifiers for the certificate ' .
1209
			'in this list. The Common Name field is automatically ' .
1210
			'added to the certificate as an Alternative Name. ' .
1211
			'The signing CA may ignore or change these values.');
1212 282b6c66 jim-p
1213
		$section->add($group);
1214
1215
		$counter++;
1216
	}
1217
1218
	$section->addInput(new Form_Button(
1219
		'addrow',
1220
		'Add',
1221
		null,
1222
		'fa-plus'
1223
	))->addClass('btn-success');
1224
1225 b35250d9 NewEraCracker
	$form->add($section);
1226 b49f31d0 Sjon Hortensius
1227 2e4372e3 Viktor G
	if (($act == 'edit') && !empty($pconfig['key'])) {
1228 96773352 jim-p
		$form->addGlobal(new Form_Button(
1229
			'exportpkey',
1230
			'Export Private Key',
1231
			null,
1232
			'fa-key'
1233
		))->addClass('btn-primary');
1234
		$form->addGlobal(new Form_Button(
1235
			'exportp12',
1236
			'Export PKCS#12',
1237
			null,
1238
			'fa-archive'
1239
		))->addClass('btn-primary');
1240
	}
1241 b49f31d0 Sjon Hortensius
1242 b35250d9 NewEraCracker
	print $form;
1243 64cc39d3 Matthew Grooms
1244 7e83055a jim-p
} elseif ($act == "csr" || (($_POST['save'] == gettext("Update")) && $input_errors)) {
1245 8f58b51b jim-p
	$form = new Form(false);
1246 308f0665 NewEraCracker
	$form->setAction('system_certmanager.php?act=csr');
1247 b29c322c Stephen Beaver
1248 5f88f964 k-paulius
	$section = new Form_Section("Complete Signing Request for " . $pconfig['descr']);
1249 b29c322c Stephen Beaver
1250 ba5c55e9 Stephen Beaver
	$section->addInput(new Form_Input(
1251
		'descr',
1252 153c3aa6 Phil Davis
		'*Descriptive name',
1253 ba5c55e9 Stephen Beaver
		'text',
1254
		$pconfig['descr']
1255
	));
1256
1257 b29c322c Stephen Beaver
	$section->addInput(new Form_Textarea(
1258
		'csr',
1259
		'Signing request data',
1260
		$pconfig['csr']
1261
	))->setReadonly()
1262 af28e231 Stephen Beaver
	  ->setWidth(7)
1263 813c6673 NOYB
	  ->setHelp('Copy the certificate signing data from here and forward it to a certificate authority for signing.');
1264 b29c322c Stephen Beaver
1265
	$section->addInput(new Form_Textarea(
1266
		'cert',
1267 153c3aa6 Phil Davis
		'*Final certificate data',
1268 b29c322c Stephen Beaver
		$pconfig['cert']
1269 af28e231 Stephen Beaver
	))->setWidth(7)
1270 813c6673 NOYB
	  ->setHelp('Paste the certificate received from the certificate authority here.');
1271 b29c322c Stephen Beaver
1272 f0b38e39 jim-p
	if (isset($id) && $thiscert) {
1273 ee12dd78 Peter Feichtinger
		$form->addGlobal(new Form_Input(
1274 b29c322c Stephen Beaver
			'id',
1275
			null,
1276
			'hidden',
1277
			$id
1278 ee12dd78 Peter Feichtinger
		));
1279 b29c322c Stephen Beaver
1280 ee12dd78 Peter Feichtinger
		$form->addGlobal(new Form_Input(
1281 b29c322c Stephen Beaver
			'act',
1282
			null,
1283
			'hidden',
1284
			'csr'
1285 ee12dd78 Peter Feichtinger
		));
1286
	}
1287 b29c322c Stephen Beaver
1288
	$form->add($section);
1289 8f58b51b jim-p
1290
	$form->addGlobal(new Form_Button(
1291 141d8913 jim-p
		'save',
1292 faab522f Renato Botelho
		'Update',
1293 8f58b51b jim-p
		null,
1294
		'fa-save'
1295
	))->addClass('btn-primary');
1296
1297 b29c322c Stephen Beaver
	print($form);
1298
} else {
1299
?>
1300 14973058 jim-p
<div class="panel panel-default" id="search-panel">
1301
	<div class="panel-heading">
1302
		<h2 class="panel-title">
1303
			<?=gettext('Search')?>
1304
			<span class="widget-heading-icon pull-right">
1305
				<a data-toggle="collapse" href="#search-panel_panel-body">
1306
					<i class="fa fa-plus-circle"></i>
1307
				</a>
1308
			</span>
1309
		</h2>
1310
	</div>
1311
	<div id="search-panel_panel-body" class="panel-body collapse in">
1312
		<div class="form-group">
1313
			<label class="col-sm-2 control-label">
1314
				<?=gettext("Search term")?>
1315
			</label>
1316
			<div class="col-sm-5"><input class="form-control" name="searchstr" id="searchstr" type="text"/></div>
1317
			<div class="col-sm-2">
1318
				<select id="where" class="form-control">
1319
					<option value="0"><?=gettext("Name")?></option>
1320
					<option value="1"><?=gettext("Distinguished Name")?></option>
1321
					<option value="2" selected><?=gettext("Both")?></option>
1322
				</select>
1323
			</div>
1324
			<div class="col-sm-3">
1325
				<a id="btnsearch" title="<?=gettext("Search")?>" class="btn btn-primary btn-sm"><i class="fa fa-search icon-embed-btn"></i><?=gettext("Search")?></a>
1326
				<a id="btnclear" title="<?=gettext("Clear")?>" class="btn btn-info btn-sm"><i class="fa fa-undo icon-embed-btn"></i><?=gettext("Clear")?></a>
1327
			</div>
1328
			<div class="col-sm-10 col-sm-offset-2">
1329 f30da999 jim-p
				<span class="help-block"><?=gettext('Enter a search string or *nix regular expression to search certificate names and distinguished names.')?></span>
1330 14973058 jim-p
			</div>
1331
		</div>
1332
	</div>
1333
</div>
1334 060ed238 Stephen Beaver
<div class="panel panel-default">
1335
	<div class="panel-heading"><h2 class="panel-title"><?=gettext('Certificates')?></h2></div>
1336
	<div class="panel-body">
1337
		<div class="table-responsive">
1338 14973058 jim-p
		<table class="table table-striped table-hover sortable-theme-bootstrap" data-sortable>
1339 060ed238 Stephen Beaver
			<thead>
1340
				<tr>
1341
					<th><?=gettext("Name")?></th>
1342
					<th><?=gettext("Issuer")?></th>
1343
					<th><?=gettext("Distinguished Name")?></th>
1344
					<th><?=gettext("In Use")?></th>
1345 4db1f211 Stephen Beaver
1346 060ed238 Stephen Beaver
					<th class="col-sm-2"><?=gettext("Actions")?></th>
1347
				</tr>
1348
			</thead>
1349
			<tbody>
1350 b29c322c Stephen Beaver
<?php
1351 4db1f211 Stephen Beaver
1352
$pluginparams = array();
1353
$pluginparams['type'] = 'certificates';
1354
$pluginparams['event'] = 'used_certificates';
1355
$certificates_used_by_packages = pkg_call_plugins('plugin_certificates', $pluginparams);
1356 f0b38e39 jim-p
foreach ($a_cert as $cert):
1357 ca4456b9 jim-p
	if (!is_array($cert) || empty($cert)) {
1358
		continue;
1359
	}
1360 b29c322c Stephen Beaver
	$name = htmlspecialchars($cert['descr']);
1361
	if ($cert['crt']) {
1362
		$subj = cert_get_subject($cert['crt']);
1363
		$issuer = cert_get_issuer($cert['crt']);
1364
		$purpose = cert_get_purpose($cert['crt']);
1365
1366 78863416 Phil Davis
		if ($subj == $issuer) {
1367 b29c322c Stephen Beaver
			$caname = '<i>'. gettext("self-signed") .'</i>';
1368 78863416 Phil Davis
		} else {
1369 b29c322c Stephen Beaver
			$caname = '<i>'. gettext("external").'</i>';
1370 78863416 Phil Davis
		}
1371 b29c322c Stephen Beaver
1372 83d2b83a jim-p
		$subj = htmlspecialchars(cert_escape_x509_chars($subj, true));
1373 1048585a PiBa-NL
	} else {
1374
		$subj = "";
1375
		$issuer = "";
1376
		$purpose = "";
1377
		$startdate = "";
1378
		$enddate = "";
1379
		$caname = "<em>" . gettext("private key only") . "</em>";
1380 b29c322c Stephen Beaver
	}
1381
1382
	if ($cert['csr']) {
1383 83d2b83a jim-p
		$subj = htmlspecialchars(cert_escape_x509_chars(csr_get_subject($cert['csr']), true));
1384 b29c322c Stephen Beaver
		$caname = "<em>" . gettext("external - signature pending") . "</em>";
1385
	}
1386
1387
	$ca = lookup_ca($cert['caref']);
1388 78863416 Phil Davis
	if ($ca) {
1389 b29c322c Stephen Beaver
		$caname = $ca['descr'];
1390 78863416 Phil Davis
	}
1391 b29c322c Stephen Beaver
?>
1392 060ed238 Stephen Beaver
				<tr>
1393
					<td>
1394
						<?=$name?><br />
1395
						<?php if ($cert['type']): ?>
1396
							<i><?=$cert_types[$cert['type']]?></i><br />
1397
						<?php endif?>
1398
						<?php if (is_array($purpose)): ?>
1399 4906f4ee jim-p
							CA: <b><?=$purpose['ca']?></b><br/>
1400
							<?=gettext("Server")?>: <b><?=$purpose['server']?></b><br/>
1401 060ed238 Stephen Beaver
						<?php endif?>
1402
					</td>
1403
					<td><?=$caname?></td>
1404
					<td>
1405
						<?=$subj?>
1406 b6196922 jim-p
						<?= cert_print_infoblock($cert); ?>
1407 93f1121f jim-p
						<?php cert_print_dates($cert);?>
1408 060ed238 Stephen Beaver
					</td>
1409
					<td>
1410
						<?php if (is_cert_revoked($cert)): ?>
1411 762faef5 Phil Davis
							<i><?=gettext("Revoked")?></i>
1412 060ed238 Stephen Beaver
						<?php endif?>
1413
						<?php if (is_webgui_cert($cert['refid'])): ?>
1414 762faef5 Phil Davis
							<?=gettext("webConfigurator")?>
1415 060ed238 Stephen Beaver
						<?php endif?>
1416
						<?php if (is_user_cert($cert['refid'])): ?>
1417 762faef5 Phil Davis
							<?=gettext("User Cert")?>
1418 060ed238 Stephen Beaver
						<?php endif?>
1419
						<?php if (is_openvpn_server_cert($cert['refid'])): ?>
1420 762faef5 Phil Davis
							<?=gettext("OpenVPN Server")?>
1421 060ed238 Stephen Beaver
						<?php endif?>
1422
						<?php if (is_openvpn_client_cert($cert['refid'])): ?>
1423 762faef5 Phil Davis
							<?=gettext("OpenVPN Client")?>
1424 060ed238 Stephen Beaver
						<?php endif?>
1425
						<?php if (is_ipsec_cert($cert['refid'])): ?>
1426 762faef5 Phil Davis
							<?=gettext("IPsec Tunnel")?>
1427 060ed238 Stephen Beaver
						<?php endif?>
1428
						<?php if (is_captiveportal_cert($cert['refid'])): ?>
1429 762faef5 Phil Davis
							<?=gettext("Captive Portal")?>
1430 060ed238 Stephen Beaver
						<?php endif?>
1431 39d83c73 Viktor G
						<?php if (is_unbound_cert($cert['refid'])): ?>
1432
							<?=gettext("DNS Resolver")?>
1433
						<?php endif?>
1434 3bde5cdd PiBa-NL
						<?php echo cert_usedby_description($cert['refid'], $certificates_used_by_packages); ?>
1435 060ed238 Stephen Beaver
					</td>
1436
					<td>
1437
						<?php if (!$cert['csr']): ?>
1438 96773352 jim-p
							<a href="system_certmanager.php?act=edit&amp;id=<?=$cert['refid']?>" class="fa fa-pencil" title="<?=gettext("Edit Certificate")?>"></a>
1439 f0b38e39 jim-p
							<a href="system_certmanager.php?act=exp&amp;id=<?=$cert['refid']?>" class="fa fa-certificate" title="<?=gettext("Export Certificate")?>"></a>
1440 4594038a Steve Beaver
							<?php if ($cert['prv']): ?>
1441 f0b38e39 jim-p
								<a href="system_certmanager.php?act=key&amp;id=<?=$cert['refid']?>" class="fa fa-key" title="<?=gettext("Export Key")?>"></a>
1442 4594038a Steve Beaver
							<?php endif?>
1443 03a84081 jim-p
							<?php if (is_cert_locally_renewable($cert)): ?>
1444
								<a href="system_certmanager_renew.php?type=cert&amp;refid=<?=$cert['refid']?>" class="fa fa-repeat" title="<?=gettext("Reissue/Renew")?>"></a>
1445 f0b38e39 jim-p
							<a href="system_certmanager.php?act=p12&amp;id=<?=$cert['refid']?>" class="fa fa-archive" title="<?=gettext("Export P12")?>"></a>
1446 2e4372e3 Viktor G
							<?php endif ?>
1447 060ed238 Stephen Beaver
						<?php else: ?>
1448 f0b38e39 jim-p
							<a href="system_certmanager.php?act=csr&amp;id=<?=$cert['refid']?>" class="fa fa-pencil" title="<?=gettext("Update CSR")?>"></a>
1449
							<a href="system_certmanager.php?act=req&amp;id=<?=$cert['refid']?>" class="fa fa-sign-in" title="<?=gettext("Export Request")?>"></a>
1450
							<a href="system_certmanager.php?act=key&amp;id=<?=$cert['refid']?>" class="fa fa-key" title="<?=gettext("Export Key")?>"></a>
1451 060ed238 Stephen Beaver
						<?php endif?>
1452
						<?php if (!cert_in_use($cert['refid'])): ?>
1453 f0b38e39 jim-p
							<a href="system_certmanager.php?act=del&amp;id=<?=$cert['refid']?>" class="fa fa-trash" title="<?=gettext("Delete Certificate")?>" usepost></a>
1454 060ed238 Stephen Beaver
						<?php endif?>
1455
					</td>
1456
				</tr>
1457 4db1f211 Stephen Beaver
<?php
1458
	endforeach; ?>
1459 060ed238 Stephen Beaver
			</tbody>
1460
		</table>
1461
		</div>
1462
	</div>
1463 b29c322c Stephen Beaver
</div>
1464
1465
<nav class="action-buttons">
1466 4611e283 Steve Beaver
	<a href="?act=new" class="btn btn-success btn-sm">
1467 b29c322c Stephen Beaver
		<i class="fa fa-plus icon-embed-btn"></i>
1468 2052d3e2 Steve Beaver
		<?=gettext("Add/Sign")?>
1469 b29c322c Stephen Beaver
	</a>
1470
</nav>
1471 14973058 jim-p
<script type="text/javascript">
1472
//<![CDATA[
1473
1474
events.push(function() {
1475
1476
	// Make these controls plain buttons
1477
	$("#btnsearch").prop('type', 'button');
1478
	$("#btnclear").prop('type', 'button');
1479
1480
	// Search for a term in the entry name and/or dn
1481
	$("#btnsearch").click(function() {
1482
		var searchstr = $('#searchstr').val().toLowerCase();
1483
		var table = $("table tbody");
1484
		var where = $('#where').val();
1485
1486
		table.find('tr').each(function (i) {
1487
			var $tds = $(this).find('td'),
1488
				shortname = $tds.eq(0).text().trim().toLowerCase(),
1489
				dn = $tds.eq(2).text().trim().toLowerCase();
1490
1491
			regexp = new RegExp(searchstr);
1492
			if (searchstr.length > 0) {
1493
				if (!(regexp.test(shortname) && (where != 1)) && !(regexp.test(dn) && (where != 0))) {
1494
					$(this).hide();
1495
				} else {
1496
					$(this).show();
1497
				}
1498
			} else {
1499
				$(this).show();	// A blank search string shows all
1500
			}
1501
		});
1502
	});
1503
1504
	// Clear the search term and unhide all rows (that were hidden during a previous search)
1505
	$("#btnclear").click(function() {
1506
		var table = $("table tbody");
1507
1508
		$('#searchstr').val("");
1509
1510
		table.find('tr').each(function (i) {
1511
			$(this).show();
1512
		});
1513
	});
1514
1515
	// Hitting the enter key will do the same as clicking the search button
1516
	$("#searchstr").on("keyup", function (event) {
1517
		if (event.keyCode == 13) {
1518
			$("#btnsearch").get(0).click();
1519
		}
1520
	});
1521
});
1522
//]]>
1523
</script>
1524 e9258698 NewEraCracker
<?php
1525 b29c322c Stephen Beaver
	include("foot.inc");
1526
	exit;
1527
}
1528
1529
1530 51583438 Stephen Beaver
?>
1531 8fd9052f Colin Fleming
<script type="text/javascript">
1532 51583438 Stephen Beaver
//<![CDATA[
1533 78863416 Phil Davis
events.push(function() {
1534 bf9d50e8 Stephen Beaver
1535 96d78012 Viktor Gurov
	$('.import_type_toggle').click(function() {
1536
		var x509 = (this.value === 'x509');
1537
		hideInput('cert', !x509);
1538
		setRequired('cert', x509);
1539
		hideInput('key', !x509);
1540
		setRequired('key', x509);
1541
		hideInput('pkcs12_cert', x509);
1542
		setRequired('pkcs12_cert', !x509);
1543
		hideInput('pkcs12_pass', x509);
1544
		hideCheckbox('pkcs12_intermediate', x509);
1545
	});
1546
	if ($('input[name=import_type]:checked').val() == 'x509') {
1547
		hideInput('pkcs12_cert', true);
1548
		setRequired('pkcs12_cert', false);
1549
		hideInput('pkcs12_pass', true);
1550
		hideCheckbox('pkcs12_intermediate', true);
1551
		hideInput('cert', false);
1552
		setRequired('cert', true);
1553
		hideInput('key', false);
1554
		setRequired('key', true);
1555 e7e4ba5a Viktor G
	} else if ($('input[name=import_type]:checked').val() == 'pkcs12') {
1556 96d78012 Viktor Gurov
		hideInput('cert', true);
1557
		setRequired('cert', false);
1558
		hideInput('key', true);
1559
		setRequired('key', false);
1560
		setRequired('pkcs12_cert', false);
1561
	}
1562
1563 51583438 Stephen Beaver
<?php if ($internal_ca_count): ?>
1564
	function internalca_change() {
1565
1566
		caref = $('#caref').val();
1567
1568
		switch (caref) {
1569
<?php
1570
			foreach ($a_ca as $ca):
1571
				if (!$ca['prv']) {
1572
					continue;
1573
				}
1574
1575 746c9afc jim-p
				$subject = @cert_get_subject_hash($ca['crt']);
1576
				if (!is_array($subject) || empty($subject)) {
1577
					continue;
1578
				}
1579 51583438 Stephen Beaver
?>
1580
				case "<?=$ca['refid'];?>":
1581 1ec79365 jim-p
					$('#dn_country').val(<?=json_encode(cert_escape_x509_chars($subject['C'], true));?>);
1582
					$('#dn_state').val(<?=json_encode(cert_escape_x509_chars($subject['ST'], true));?>);
1583
					$('#dn_city').val(<?=json_encode(cert_escape_x509_chars($subject['L'], true));?>);
1584
					$('#dn_organization').val(<?=json_encode(cert_escape_x509_chars($subject['O'], true));?>);
1585
					$('#dn_organizationalunit').val(<?=json_encode(cert_escape_x509_chars($subject['OU'], true));?>);
1586 51583438 Stephen Beaver
					break;
1587
<?php
1588
			endforeach;
1589
?>
1590
		}
1591
	}
1592
1593 2052d3e2 Steve Beaver
	function set_csr_ro() {
1594 b078cd59 Steve Beaver
		var newcsr = ($('#csrtosign').val() == "new");
1595 65d735f0 Steve Beaver
1596
		$('#csrpaste').attr('readonly', !newcsr);
1597 55047259 Steve Beaver
		$('#keypaste').attr('readonly', !newcsr);
1598 65d735f0 Steve Beaver
		setRequired('csrpaste', newcsr);
1599 2052d3e2 Steve Beaver
	}
1600
1601 3f0b7bc3 jim-p
	function check_lifetime() {
1602
		var maxserverlife = <?= $cert_strict_values['max_server_cert_lifetime'] ?>;
1603
		var ltid = '#lifetime';
1604
		if ($('#method').val() == "sign") {
1605
			ltid = '#csrsign_lifetime';
1606
		}
1607
		if (($('#type').val() == "server") && (parseInt($(ltid).val()) > maxserverlife)) {
1608
			$(ltid).parent().parent().removeClass("text-normal").addClass("text-warning");
1609
			$(ltid).removeClass("text-normal").addClass("text-warning");
1610
		} else {
1611
			$(ltid).parent().parent().removeClass("text-warning").addClass("text-normal");
1612
			$(ltid).removeClass("text-warning").addClass("text-normal");
1613
		}
1614
	}
1615
	function check_keylen() {
1616
		var min_keylen = <?= $cert_strict_values['min_private_key_bits'] ?>;
1617
		var klid = '#keylen';
1618
		if ($('#method').val() == "external") {
1619
			klid = '#csr_keylen';
1620
		}
1621
		/* Color the Parent/Label */
1622
		if (parseInt($(klid).val()) < min_keylen) {
1623
			$(klid).parent().parent().removeClass("text-normal").addClass("text-warning");
1624
		} else {
1625
			$(klid).parent().parent().removeClass("text-warning").addClass("text-normal");
1626
		}
1627
		/* Color individual options */
1628
		$(klid + " option").filter(function() {
1629
			return parseInt($(this).val()) < min_keylen;
1630
		}).removeClass("text-normal").addClass("text-warning").siblings().removeClass("text-warning").addClass("text-normal");
1631
	}
1632
1633
	function check_digest() {
1634
		var weak_algs = <?= json_encode($cert_strict_values['digest_blacklist']) ?>;
1635
		var daid = '#digest_alg';
1636
		if ($('#method').val() == "external") {
1637
			daid = '#csr_digest_alg';
1638
		} else if ($('#method').val() == "sign") {
1639
			daid = '#csrsign_digest_alg';
1640
		}
1641
		/* Color the Parent/Label */
1642
		if (jQuery.inArray($(daid).val(), weak_algs) > -1) {
1643
			$(daid).parent().parent().removeClass("text-normal").addClass("text-warning");
1644
		} else {
1645
			$(daid).parent().parent().removeClass("text-warning").addClass("text-normal");
1646
		}
1647
		/* Color individual options */
1648
		$(daid + " option").filter(function() {
1649
			return (jQuery.inArray($(this).val(), weak_algs) > -1);
1650
		}).removeClass("text-normal").addClass("text-warning").siblings().removeClass("text-warning").addClass("text-normal");
1651
	}
1652
1653 eef93144 Jared Dillard
	// ---------- Click checkbox handlers ---------------------------------------------------------
1654 f74457df Stephen Beaver
1655 3f0b7bc3 jim-p
	$('#type').on('change', function() {
1656
		check_lifetime();
1657
	});
1658
	$('#method').on('change', function() {
1659
		check_lifetime();
1660
		check_keylen();
1661
		check_digest();
1662
	});
1663
	$('#lifetime').on('change', function() {
1664
		check_lifetime();
1665
	});
1666
	$('#csrsign_lifetime').on('change', function() {
1667
		check_lifetime();
1668
	});
1669
1670
	$('#keylen').on('change', function() {
1671
		check_keylen();
1672
	});
1673
	$('#csr_keylen').on('change', function() {
1674
		check_keylen();
1675
	});
1676
1677
	$('#digest_alg').on('change', function() {
1678
		check_digest();
1679
	});
1680
	$('#csr_digest_alg').on('change', function() {
1681
		check_digest();
1682
	});
1683
1684 51583438 Stephen Beaver
	$('#caref').on('change', function() {
1685
		internalca_change();
1686
	});
1687
1688 2052d3e2 Steve Beaver
	$('#csrtosign').change(function () {
1689
		set_csr_ro();
1690
	});
1691
1692 dace81a7 Viktor Gurov
	function change_keytype() {
1693 e655d548 jim-p
		hideClass('rsakeys', ($('#keytype').val() != 'RSA'));
1694
		hideClass('ecnames', ($('#keytype').val() != 'ECDSA'));
1695
	}
1696 dace81a7 Viktor Gurov
1697
	$('#keytype').change(function () {
1698 e655d548 jim-p
		change_keytype();
1699
	});
1700 dace81a7 Viktor Gurov
1701
	function change_csrkeytype() {
1702 e655d548 jim-p
		hideClass('csr_rsakeys', ($('#csr_keytype').val() != 'RSA'));
1703
		hideClass('csr_ecnames', ($('#csr_keytype').val() != 'ECDSA'));
1704
	}
1705 dace81a7 Viktor Gurov
1706
	$('#csr_keytype').change(function () {
1707 e655d548 jim-p
		change_csrkeytype();
1708
	});
1709 dace81a7 Viktor Gurov
1710 eef93144 Jared Dillard
	// ---------- On initial page load ------------------------------------------------------------
1711
1712 51583438 Stephen Beaver
	internalca_change();
1713 2052d3e2 Steve Beaver
	set_csr_ro();
1714 dace81a7 Viktor Gurov
	change_keytype();
1715
	change_csrkeytype();
1716 3f0b7bc3 jim-p
	check_lifetime();
1717
	check_keylen();
1718
	check_digest();
1719 51583438 Stephen Beaver
1720 0bc61baa Stephen Beaver
	// Suppress "Delete row" button if there are fewer than two rows
1721
	checkLastRow();
1722
1723 dace81a7 Viktor Gurov
1724 51583438 Stephen Beaver
<?php endif; ?>
1725
1726
1727
});
1728
//]]>
1729
</script>
1730
<?php
1731 0edcccc3 Daniel Seebald
include('foot.inc');