Project

General

Profile

Download (53.6 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 8f2f85c3 Luiz Otavio O Souza
 * Copyright (c) 2014-2022 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 46bd32bb Steve Beaver
init_config_arr(array('ca'));
68
$a_ca = &$config['ca'];
69
70
init_config_arr(array('cert'));
71
$a_cert = &$config['cert'];
72
73 64cc39d3 Matthew Grooms
$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 fe31d06f Viktor G
		$pattern = '/[^a-zA-Z0-9\ \'\/~`\!@#\$%\^&\*\(\)_\-\+=\{\}\[\]\|;:"\<\>,\.\?\\\]/';
377
		if (!empty($_POST['dn_commonname']) && preg_match($pattern, $_POST['dn_commonname'])) {
378
			$input_errors[] = gettext("The field 'Common Name' contains invalid characters.");
379
		}
380
		if (!empty($_POST['dn_state']) && preg_match($pattern, $_POST['dn_state'])) {
381
			$input_errors[] = gettext("The field 'State or Province' contains invalid characters.");
382
		}
383
		if (!empty($_POST['dn_city']) && preg_match($pattern, $_POST['dn_city'])) {
384
			$input_errors[] = gettext("The field 'City' contains invalid characters.");
385
		}
386
		if (!empty($_POST['dn_organization']) && preg_match($pattern, $_POST['dn_organization'])) {
387
			$input_errors[] = gettext("The field 'Organization' contains invalid characters.");
388
		}
389
		if (!empty($_POST['dn_organizationalunit']) && preg_match($pattern, $_POST['dn_organizationalunit'])) {
390
			$input_errors[] = gettext("The field 'Organizational Unit' contains invalid characters.");
391
		}
392 64cc39d3 Matthew Grooms
393 7e83055a jim-p
		switch ($pconfig['method']) {
394
			case "internal":
395
				if (isset($_POST["keytype"]) && !in_array($_POST["keytype"], $cert_keytypes)) {
396
					$input_errors[] = gettext("Please select a valid Key Type.");
397 56b1ed39 Phil Davis
				}
398 7e83055a jim-p
				if (isset($_POST["keylen"]) && !in_array($_POST["keylen"], $cert_keylens)) {
399
					$input_errors[] = gettext("Please select a valid Key Length.");
400 2052d3e2 Steve Beaver
				}
401 cffcf9bf jim-p
				if (isset($_POST["ecname"]) && !in_array($_POST["ecname"], array_keys($openssl_ecnames))) {
402 7e83055a jim-p
					$input_errors[] = gettext("Please select a valid Elliptic Curve Name.");
403
				}
404
				if (!in_array($_POST["digest_alg"], $openssl_digest_algs)) {
405
					$input_errors[] = gettext("Please select a valid Digest Algorithm.");
406
				}
407
				break;
408
			case "external":
409
				if (isset($_POST["csr_keytype"]) && !in_array($_POST["csr_keytype"], $cert_keytypes)) {
410
					$input_errors[] = gettext("Please select a valid Key Type.");
411 55047259 Steve Beaver
				}
412 7e83055a jim-p
				if (isset($_POST["csr_keylen"]) && !in_array($_POST["csr_keylen"], $cert_keylens)) {
413
					$input_errors[] = gettext("Please select a valid Key Length.");
414
				}
415 cffcf9bf jim-p
				if (isset($_POST["csr_ecname"]) && !in_array($_POST["csr_ecname"], array_keys($openssl_ecnames))) {
416 7e83055a jim-p
					$input_errors[] = gettext("Please select a valid Elliptic Curve Name.");
417
				}
418
				if (!in_array($_POST["csr_digest_alg"], $openssl_digest_algs)) {
419
					$input_errors[] = gettext("Please select a valid Digest Algorithm.");
420
				}
421
				break;
422
			case "sign":
423
				if (!in_array($_POST["csrsign_digest_alg"], $openssl_digest_algs)) {
424
					$input_errors[] = gettext("Please select a valid Digest Algorithm.");
425
				}
426
				break;
427
			default:
428
				break;
429
		}
430
	}
431 2052d3e2 Steve Beaver
432 7e83055a jim-p
	/* save modifications */
433
	if (!$input_errors) {
434 96773352 jim-p
		$old_err_level = error_reporting(0); /* otherwise openssl_ functions throw warnings directly to a page breaking menu tabs */
435 b078cd59 Steve Beaver
436 96773352 jim-p
		if (isset($id) && $thiscert) {
437
			$cert = $thiscert;
438 7e83055a jim-p
		} else {
439
			$cert = array();
440
			$cert['refid'] = uniqid();
441 96773352 jim-p
		}
442 ad9b5c67 jim-p
443 96773352 jim-p
		$cert['descr'] = $pconfig['descr'];
444 282b6c66 jim-p
445 96773352 jim-p
		switch($pconfig['method']) {
446
			case 'existing':
447
				/* Add an existing certificate to a user */
448
				$ucert = lookup_cert($pconfig['certref']);
449
				if ($ucert && $a_user) {
450
					$a_user[$userid]['cert'][] = $ucert['refid'];
451
					$savemsg = sprintf(gettext("Added certificate %s to user %s"), $ucert['descr'], $a_user[$userid]['name']);
452
				}
453
				unset($cert);
454
				break;
455
			case 'sign':
456
				/* Sign a CSR */
457
				$csrid = lookup_cert($pconfig['csrtosign']);
458
				$ca = & lookup_ca($pconfig['catosignwith']);
459
				// Read the CSR from $config, or if a new one, from the textarea
460
				if ($pconfig['csrtosign'] === "new") {
461
					$csr = $pconfig['csrpaste'];
462
				} else {
463
					$csr = base64_decode($csrid['csr']);
464
				}
465
				if (count($altnames)) {
466
					foreach ($altnames as $altname) {
467 692510f2 Viktor G
						$altnames_tmp[] = "{$altname['type']}:" . $altname['value'];
468 96773352 jim-p
					}
469
					$altname_str = implode(",", $altnames_tmp);
470
				}
471
				$n509 = csr_sign($csr, $ca, $pconfig['csrsign_lifetime'], $pconfig['type'], $altname_str, $pconfig['csrsign_digest_alg']);
472
				if ($n509) {
473
					// Gather the details required to save the new cert
474
					$newcert = array();
475
					$newcert['refid'] = uniqid();
476
					$newcert['caref'] = $pconfig['catosignwith'];
477
					$newcert['descr'] = $pconfig['descr'];
478
					$newcert['type'] = $pconfig['type'];
479
					$newcert['crt'] = base64_encode($n509);
480
					if ($pconfig['csrtosign'] === "new") {
481
						$newcert['prv'] = base64_encode($pconfig['keypaste']);
482
					} else {
483
						$newcert['prv'] = $csrid['prv'];
484
					}
485
					// Add it to the config file
486
					$config['cert'][] = $newcert;
487
					$savemsg = sprintf(gettext("Signed certificate %s"), $newcert['descr']);
488
				}
489
				unset($cert);
490
				break;
491
			case 'edit':
492
				cert_import($cert, $pconfig['cert'], $pconfig['key']);
493
				$savemsg = sprintf(gettext("Edited certificate %s"), $cert['descr']);
494
				break;
495
			case 'import':
496
				/* Import an external certificate+key */
497 96d78012 Viktor Gurov
				if ($pkcs12_data) {
498
					$pconfig['cert'] = $pkcs12_data['cert'];
499
					$pconfig['key'] = $pkcs12_data['pkey'];
500
					if ($_POST['pkcs12_intermediate'] && is_array($pkcs12_data['extracerts'])) {
501
						foreach ($pkcs12_data['extracerts'] as $intermediate) {
502
							$int_data = openssl_x509_parse($intermediate);
503
							if (!$int_data) continue;
504
							$cn = $int_data['subject']['CN'];
505
							$int_ca = array('descr' => $cn, 'refid' => uniqid());
506
							if (ca_import($int_ca, $intermediate)) {
507
								$a_ca[] = $int_ca;
508
							}
509
						}
510
					}
511
				}
512 7e83055a jim-p
				cert_import($cert, $pconfig['cert'], $pconfig['key']);
513 f0b38e39 jim-p
				$savemsg = sprintf(gettext("Imported certificate %s"), $cert['descr']);
514 96773352 jim-p
				break;
515
			case 'internal':
516
				/* Create an internal certificate */
517 692510f2 Viktor G
				$dn = array('commonName' => $pconfig['dn_commonname']);
518 7e83055a jim-p
				if (!empty($pconfig['dn_country'])) {
519
					$dn['countryName'] = $pconfig['dn_country'];
520
				}
521
				if (!empty($pconfig['dn_state'])) {
522 692510f2 Viktor G
					$dn['stateOrProvinceName'] = $pconfig['dn_state'];
523 7e83055a jim-p
				}
524
				if (!empty($pconfig['dn_city'])) {
525 692510f2 Viktor G
					$dn['localityName'] = $pconfig['dn_city'];
526 7e83055a jim-p
				}
527
				if (!empty($pconfig['dn_organization'])) {
528 692510f2 Viktor G
					$dn['organizationName'] = $pconfig['dn_organization'];
529 7e83055a jim-p
				}
530
				if (!empty($pconfig['dn_organizationalunit'])) {
531 692510f2 Viktor G
					$dn['organizationalUnitName'] = $pconfig['dn_organizationalunit'];
532 7e83055a jim-p
				}
533
				$altnames_tmp = array();
534
				$cn_altname = cert_add_altname_type($pconfig['dn_commonname']);
535
				if (!empty($cn_altname)) {
536
					$altnames_tmp[] = $cn_altname;
537
				}
538
				if (count($altnames)) {
539
					foreach ($altnames as $altname) {
540
						// The CN is added as a SAN automatically, do not add it again.
541
						if ($altname['value'] != $pconfig['dn_commonname']) {
542 692510f2 Viktor G
							$altnames_tmp[] = "{$altname['type']}:" . $altname['value'];
543 2f65de89 jim-p
						}
544 282b6c66 jim-p
					}
545 7e83055a jim-p
				}
546
				if (!empty($altnames_tmp)) {
547
					$dn['subjectAltName'] = implode(",", $altnames_tmp);
548
				}
549
				if (!cert_create($cert, $pconfig['caref'], $pconfig['keylen'], $pconfig['lifetime'], $dn, $pconfig['type'], $pconfig['digest_alg'], $pconfig['keytype'], $pconfig['ecname'])) {
550
					$input_errors = array();
551
					while ($ssl_err = openssl_error_string()) {
552
						if (strpos($ssl_err, 'NCONF_get_string:no value') === false) {
553
							$input_errors[] = sprintf(gettext("OpenSSL Library Error: %s"), $ssl_err);
554 22b380aa Evgeny Yurchenko
						}
555
					}
556 ad9b5c67 jim-p
				}
557 f0b38e39 jim-p
				$savemsg = sprintf(gettext("Created internal certificate %s"), $cert['descr']);
558 96773352 jim-p
				break;
559
			case 'external':
560
				/* Create a certificate signing request */
561 692510f2 Viktor G
				$dn = array('commonName' => $pconfig['csr_dn_commonname']);
562 7e83055a jim-p
				if (!empty($pconfig['csr_dn_country'])) {
563
					$dn['countryName'] = $pconfig['csr_dn_country'];
564
				}
565
				if (!empty($pconfig['csr_dn_state'])) {
566 692510f2 Viktor G
					$dn['stateOrProvinceName'] = $pconfig['csr_dn_state'];
567 7e83055a jim-p
				}
568
				if (!empty($pconfig['csr_dn_city'])) {
569 692510f2 Viktor G
					$dn['localityName'] = $pconfig['csr_dn_city'];
570 7e83055a jim-p
				}
571
				if (!empty($pconfig['csr_dn_organization'])) {
572 692510f2 Viktor G
					$dn['organizationName'] = $pconfig['csr_dn_organization'];
573 7e83055a jim-p
				}
574
				if (!empty($pconfig['csr_dn_organizationalunit'])) {
575 692510f2 Viktor G
					$dn['organizationalUnitName'] = $pconfig['csr_dn_organizationalunit'];
576 7e83055a jim-p
				}
577
				$altnames_tmp = array();
578
				$cn_altname = cert_add_altname_type($pconfig['csr_dn_commonname']);
579
				if (!empty($cn_altname)) {
580
					$altnames_tmp[] = $cn_altname;
581
				}
582
				if (count($altnames)) {
583
					foreach ($altnames as $altname) {
584
						// The CN is added as a SAN automatically, do not add it again.
585
						if ($altname['value'] != $pconfig['csr_dn_commonname']) {
586 692510f2 Viktor G
							$altnames_tmp[] = "{$altname['type']}:" . $altname['value'];
587 7e83055a jim-p
						}
588
					}
589
				}
590
				if (!empty($altnames_tmp)) {
591
					$dn['subjectAltName'] = implode(",", $altnames_tmp);
592 56b1ed39 Phil Davis
				}
593 7e83055a jim-p
				if (!csr_generate($cert, $pconfig['csr_keylen'], $dn, $pconfig['type'], $pconfig['csr_digest_alg'], $pconfig['csr_keytype'], $pconfig['csr_ecname'])) {
594
					$input_errors = array();
595
					while ($ssl_err = openssl_error_string()) {
596
						if (strpos($ssl_err, 'NCONF_get_string:no value') === false) {
597
							$input_errors[] = sprintf(gettext("OpenSSL Library Error: %s"), $ssl_err);
598
						}
599
					}
600 56b1ed39 Phil Davis
				}
601 f0b38e39 jim-p
				$savemsg = sprintf(gettext("Created certificate signing request %s"), $cert['descr']);
602 96773352 jim-p
				break;
603
			default:
604
				break;
605
		}
606
		error_reporting($old_err_level);
607 7e83055a jim-p
608 96773352 jim-p
		if (isset($id) && $thiscert) {
609
			$thiscert = $cert;
610
		} elseif ($cert) {
611
			$a_cert[] = $cert;
612
		}
613 64cc39d3 Matthew Grooms
614 96773352 jim-p
		if (isset($a_user) && isset($userid)) {
615
			$a_user[$userid]['cert'][] = $cert['refid'];
616 64cc39d3 Matthew Grooms
		}
617
618 7e83055a jim-p
		if (!$input_errors) {
619 f0b38e39 jim-p
			write_config($savemsg);
620 b741d2ef jim-p
		}
621
622 7e83055a jim-p
		if ((isset($userid) && is_numeric($userid)) && !$input_errors) {
623
			post_redirect("system_usermanager.php", array('act' => 'edit', 'userid' => $userid));
624
			exit;
625 a828210b yakatz
		}
626 7e83055a jim-p
	}
627
} elseif ($_POST['save'] == gettext("Update")) {
628
	/* Updating a certificate signing request */
629
	unset($input_errors);
630
	$pconfig = $_POST;
631 64cc39d3 Matthew Grooms
632 7e83055a jim-p
	/* input validation */
633
	$reqdfields = explode(" ", "descr cert");
634
	$reqdfieldsn = array(
635
		gettext("Descriptive name"),
636
		gettext("Final Certificate data"));
637 64cc39d3 Matthew Grooms
638 7e83055a jim-p
	do_input_validation($_POST, $reqdfields, $reqdfieldsn, $input_errors);
639 64cc39d3 Matthew Grooms
640 7e83055a jim-p
	if (preg_match("/[\?\>\<\&\/\\\"\']/", $_POST['descr'])) {
641
		$input_errors[] = gettext("The field 'Descriptive Name' contains invalid characters.");
642
	}
643 64cc39d3 Matthew Grooms
644 7e83055a jim-p
	$mod_csr = cert_get_publickey($pconfig['csr'], false, 'csr');
645
	$mod_cert = cert_get_publickey($pconfig['cert'], false);
646 64cc39d3 Matthew Grooms
647 7e83055a jim-p
	if (strcmp($mod_csr, $mod_cert)) {
648
		// simply: if the moduli don't match, then the private key and public key won't match
649
		$input_errors[] = gettext("The certificate public key does not match the signing request public key.");
650
		$subject_mismatch = true;
651
	}
652 64cc39d3 Matthew Grooms
653 7e83055a jim-p
	/* save modifications */
654
	if (!$input_errors) {
655 f0b38e39 jim-p
		$cert = $thiscert;
656 7e83055a jim-p
		$cert['descr'] = $pconfig['descr'];
657
		csr_complete($cert, $pconfig['cert']);
658 f0b38e39 jim-p
		$thiscert = $cert;
659
		$savemsg = sprintf(gettext("Updated certificate signing request %s"), $pconfig['descr']);
660
		write_config($savemsg);
661 7e83055a jim-p
		pfSenseHeader("system_certmanager.php");
662 64cc39d3 Matthew Grooms
	}
663
}
664
665 56c6b1cb k-paulius
$pgtitle = array(gettext("System"), gettext("Certificate Manager"), gettext("Certificates"));
666 edcd7535 Phil Davis
$pglinks = array("", "system_camanager.php", "system_certmanager.php");
667 56c6b1cb k-paulius
668 7e83055a jim-p
if (($act == "new" || ($_POST['save'] == gettext("Save") && $input_errors)) ||
669
    ($act == "csr" || ($_POST['save'] == gettext("Update") && $input_errors))) {
670 56c6b1cb k-paulius
	$pgtitle[] = gettext('Edit');
671 edcd7535 Phil Davis
	$pglinks[] = "@self";
672 56c6b1cb k-paulius
}
673 64cc39d3 Matthew Grooms
include("head.inc");
674 b49f31d0 Sjon Hortensius
675 78863416 Phil Davis
if ($input_errors) {
676 b49f31d0 Sjon Hortensius
	print_input_errors($input_errors);
677 78863416 Phil Davis
}
678 0edcccc3 Daniel Seebald
679 78863416 Phil Davis
if ($savemsg) {
680 f0b38e39 jim-p
	print_info_box($savemsg, $class);
681 78863416 Phil Davis
}
682 b49f31d0 Sjon Hortensius
683
$tab_array = array();
684
$tab_array[] = array(gettext("CAs"), false, "system_camanager.php");
685
$tab_array[] = array(gettext("Certificates"), true, "system_certmanager.php");
686
$tab_array[] = array(gettext("Certificate Revocation"), false, "system_crlmanager.php");
687
display_top_tabs($tab_array);
688
689 96773352 jim-p
if (in_array($act, array('new', 'edit')) || (($_POST['save'] == gettext("Save")) && $input_errors)) {
690 b35250d9 NewEraCracker
	$form = new Form();
691 96d78012 Viktor Gurov
	$form->setAction('system_certmanager.php')->setMultipartEncoding();
692 b49f31d0 Sjon Hortensius
693 b35250d9 NewEraCracker
	if (isset($userid) && $a_user) {
694
		$form->addGlobal(new Form_Input(
695
			'userid',
696
			null,
697
			'hidden',
698
			$userid
699
		));
700
	}
701 b49f31d0 Sjon Hortensius
702 f0b38e39 jim-p
	if (isset($id) && $thiscert) {
703 b49f31d0 Sjon Hortensius
		$form->addGlobal(new Form_Input(
704
			'id',
705
			null,
706
			'hidden',
707
			$id
708
		));
709 64cc39d3 Matthew Grooms
	}
710 b49f31d0 Sjon Hortensius
711 96773352 jim-p
	switch ($act) {
712
		case 'edit':
713
			$maintitle = gettext('Edit an Existing Certificate');
714
			break;
715
		case 'new':
716
		default:
717
			$maintitle = gettext('Add/Sign a New Certificate');
718
			break;
719
	}
720
721
	$section = new Form_Section($maintitle);
722 b35250d9 NewEraCracker
723 96773352 jim-p
	if (!isset($id) || ($act == 'edit')) {
724 b35250d9 NewEraCracker
		$section->addInput(new Form_Select(
725
			'method',
726 153c3aa6 Phil Davis
			'*Method',
727 b35250d9 NewEraCracker
			$pconfig['method'],
728
			$cert_methods
729
		))->toggles();
730
	}
731
732 b49f31d0 Sjon Hortensius
	$section->addInput(new Form_Input(
733
		'descr',
734 153c3aa6 Phil Davis
		'*Descriptive name',
735 b49f31d0 Sjon Hortensius
		'text',
736 b35250d9 NewEraCracker
		($a_user && empty($pconfig['descr'])) ? $a_user[$userid]['name'] : $pconfig['descr']
737 96773352 jim-p
	))->addClass('toggle-internal toggle-import toggle-edit toggle-external toggle-sign toggle-existing collapse');
738
739
	if (!empty($pconfig['cert'])) {
740
		$section->addInput(new Form_StaticText(
741
			"Subject",
742
			htmlspecialchars(cert_get_subject($pconfig['cert'], false))
743
		))->addClass('toggle-edit collapse');
744
	}
745 b49f31d0 Sjon Hortensius
746 b35250d9 NewEraCracker
	$form->add($section);
747 2052d3e2 Steve Beaver
748 46bd32bb Steve Beaver
	// Return an array containing the IDs od all CAs
749
	function list_cas() {
750
		global $a_ca;
751
		$allCas = array();
752
753
		foreach ($a_ca as $ca) {
754
			if ($ca['prv']) {
755
				$allCas[$ca['refid']] = $ca['descr'];
756
			}
757
		}
758
759
		return $allCas;
760
	}
761
762
	// Return an array containing the IDs od all CSRs
763
	function list_csrs() {
764
		global $config;
765
		$allCsrs = array();
766
767
		foreach ($config['cert'] as $cert) {
768
			if ($cert['csr']) {
769
				$allCsrs[$cert['refid']] = $cert['descr'];
770
			}
771
		}
772
773
		return ['new' => gettext('New CSR (Paste below)')] + $allCsrs;
774
	}
775
776 2052d3e2 Steve Beaver
	$section = new Form_Section('Sign CSR');
777
	$section->addClass('toggle-sign collapse');
778
779
	$section->AddInput(new Form_Select(
780
		'catosignwith',
781
		'*CA to sign with',
782
		$pconfig['catosignwith'],
783
		list_cas()
784
	));
785
786
	$section->AddInput(new Form_Select(
787
		'csrtosign',
788
		'*CSR to sign',
789
		isset($pconfig['csrtosign']) ? $pconfig['csrtosign'] : 'new',
790
		list_csrs()
791
	));
792
793
	$section->addInput(new Form_Textarea(
794
		'csrpaste',
795
		'CSR data',
796
		$pconfig['csrpaste']
797
	))->setHelp('Paste a Certificate Signing Request in X.509 PEM format here.');
798
799 55047259 Steve Beaver
	$section->addInput(new Form_Textarea(
800
		'keypaste',
801
		'Key data',
802
		$pconfig['keypaste']
803 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']);
804 55047259 Steve Beaver
805 0c82b8c2 jim-p
	$section->addInput(new Form_Input(
806
		'csrsign_lifetime',
807
		'*Certificate Lifetime (days)',
808
		'number',
809 3a877e4a jim-p
		$pconfig['csrsign_lifetime'] ? $pconfig['csrsign_lifetime']:$default_lifetime,
810
		['max' => $max_lifetime]
811 3f0b7bc3 jim-p
	))->setHelp('The length of time the signed certificate will be valid, in days. %1$s' .
812 f944f4a7 jim-p
		'Server certificates should not have a lifetime over %2$s days or some platforms ' .
813
		'may consider the certificate invalid.', '<br/>', $cert_strict_values['max_server_cert_lifetime']);
814 aec3a259 jim-p
	$section->addInput(new Form_Select(
815
		'csrsign_digest_alg',
816
		'*Digest Algorithm',
817
		$pconfig['csrsign_digest_alg'],
818
		array_combine($openssl_digest_algs, $openssl_digest_algs)
819 3f0b7bc3 jim-p
	))->setHelp('The digest method used when the certificate is signed. %1$s' .
820
		'The best practice is to use an algorithm stronger than SHA1. '.
821
		'Some platforms may consider weaker digest algorithms invalid', '<br/>');
822 0c82b8c2 jim-p
823 2052d3e2 Steve Beaver
	$form->add($section);
824
825 96773352 jim-p
	if ($act == 'edit') {
826
		$editimport = gettext("Edit Certificate");
827
	} else {
828
		$editimport = gettext("Import Certificate");
829
	}
830
831
	$section = new Form_Section($editimport);
832
	$section->addClass('toggle-import toggle-edit collapse');
833 b49f31d0 Sjon Hortensius
834 96d78012 Viktor Gurov
	$group = new Form_Group('Certificate Type');
835
836
	$group->add(new Form_Checkbox(
837
		'import_type',
838
		'Certificate Type',
839
		'X.509 (PEM)',
840
		(!isset($pconfig['import_type']) || $pconfig['import_type'] == 'x509'),
841
		'x509'
842
	))->displayAsRadio()->addClass('import_type_toggle');
843
844
	$group->add(new Form_Checkbox(
845
		'import_type',
846
		'Certificate Type',
847
		'PKCS #12 (PFX)',
848
		(isset($pconfig['import_type']) && $pconfig['import_type'] == 'pkcs12'),
849
		'pkcs12'
850
	))->displayAsRadio()->addClass('import_type_toggle');
851
852
	$section->add($group);
853
854 b49f31d0 Sjon Hortensius
	$section->addInput(new Form_Textarea(
855
		'cert',
856 153c3aa6 Phil Davis
		'*Certificate data',
857 78863416 Phil Davis
		$pconfig['cert']
858 b35250d9 NewEraCracker
	))->setHelp('Paste a certificate in X.509 PEM format here.');
859
860
	$section->addInput(new Form_Textarea(
861
		'key',
862 8c145373 Viktor G
		'Private key data',
863 b35250d9 NewEraCracker
		$pconfig['key']
864 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.');
865 b49f31d0 Sjon Hortensius
866 96d78012 Viktor Gurov
	$section->addInput(new Form_Input(
867
		'pkcs12_cert',
868
		'PKCS #12 certificate',
869
		'file',
870
		$pconfig['pkcs12_cert']
871
	))->setHelp('Select a PKCS #12 certificate store.');
872
873
	$section->addInput(new Form_Input(
874
		'pkcs12_pass',
875
		'PKCS #12 certificate password',
876
		'password',
877
		$pconfig['pkcs12_pass']
878
	))->setHelp('Enter the password to unlock the PKCS #12 certificate store.');
879
880
	$section->addInput(new Form_Checkbox(
881
		'pkcs12_intermediate',
882
		'Intermediates',
883
		'Import intermediate CAs',
884
		isset($pconfig['pkcs12_intermediate'])
885
	))->setHelp('Import any intermediate certificate authorities found in the PKCS #12 certificate store.');
886
887 67b49e4c Viktor G
	if ($act == 'edit') {
888
		$section->addInput(new Form_Input(
889
			'exportpass',
890
			'Export Password',
891
			'password',
892
			null,
893
			['placeholder' => gettext('Export Password'), 'autocomplete' => 'new-password']
894
		))->setHelp('Enter the password to use when using the export buttons below (not stored)')->addClass('toggle-edit collapse');
895
	}
896 96773352 jim-p
897 b49f31d0 Sjon Hortensius
	$form->add($section);
898 b35250d9 NewEraCracker
	$section = new Form_Section('Internal Certificate');
899
	$section->addClass('toggle-internal collapse');
900
901
	if (!$internal_ca_count) {
902
		$section->addInput(new Form_StaticText(
903 153c3aa6 Phil Davis
			'*Certificate authority',
904 781d9ce4 Phil Davis
			gettext('No internal Certificate Authorities have been defined. ') .
905
			gettext('An internal CA must be defined in order to create an internal certificate. ') .
906
			sprintf(gettext('%1$sCreate%2$s an internal CA.'), '<a href="system_camanager.php?act=new&amp;method=internal"> ', '</a>')
907 b35250d9 NewEraCracker
		));
908
	} else {
909
		$allCas = array();
910
		foreach ($a_ca as $ca) {
911
			if (!$ca['prv']) {
912
				continue;
913
			}
914 b49f31d0 Sjon Hortensius
915 b35250d9 NewEraCracker
			$allCas[ $ca['refid'] ] = $ca['descr'];
916
		}
917 64cc39d3 Matthew Grooms
918 b35250d9 NewEraCracker
		$section->addInput(new Form_Select(
919
			'caref',
920 153c3aa6 Phil Davis
			'*Certificate authority',
921 b35250d9 NewEraCracker
			$pconfig['caref'],
922
			$allCas
923
		));
924
	}
925 64cc39d3 Matthew Grooms
926 b35250d9 NewEraCracker
	$section->addInput(new Form_Select(
927 47c46bbd Viktor Gurov
		'keytype',
928
		'*Key type',
929
		$pconfig['keytype'],
930
		array_combine($cert_keytypes, $cert_keytypes)
931
	));
932
933 dace81a7 Viktor Gurov
	$group = new Form_Group($i == 0 ? '*Key length':'');
934 e0f8d364 Viktor Gurov
	$group->addClass('rsakeys');
935 dace81a7 Viktor Gurov
	$group->add(new Form_Select(
936 b35250d9 NewEraCracker
		'keylen',
937 dace81a7 Viktor Gurov
		null,
938 b35250d9 NewEraCracker
		$pconfig['keylen'],
939
		array_combine($cert_keylens, $cert_keylens)
940 3f0b7bc3 jim-p
	))->setHelp('The length to use when generating a new RSA key, in bits. %1$s' .
941
		'The Key Length should not be lower than 2048 or some platforms ' .
942
		'may consider the certificate invalid.', '<br/>');
943 dace81a7 Viktor Gurov
	$section->add($group);
944
945 e0f8d364 Viktor Gurov
	$group = new Form_Group($i == 0 ? '*Elliptic Curve Name':'');
946 2d13c7fc Viktor Gurov
	$group->addClass('ecnames');
947 dace81a7 Viktor Gurov
	$group->add(new Form_Select(
948 e0f8d364 Viktor Gurov
		'ecname',
949 dace81a7 Viktor Gurov
		null,
950 e0f8d364 Viktor Gurov
		$pconfig['ecname'],
951 cffcf9bf jim-p
		$openssl_ecnames
952
	))->setHelp('Curves may not be compatible with all uses. Known compatible curve uses are denoted in brackets.');
953 dace81a7 Viktor Gurov
	$section->add($group);
954 64cc39d3 Matthew Grooms
955 b35250d9 NewEraCracker
	$section->addInput(new Form_Select(
956
		'digest_alg',
957 153c3aa6 Phil Davis
		'*Digest Algorithm',
958 b35250d9 NewEraCracker
		$pconfig['digest_alg'],
959
		array_combine($openssl_digest_algs, $openssl_digest_algs)
960 3f0b7bc3 jim-p
	))->setHelp('The digest method used when the certificate is signed. %1$s' .
961
		'The best practice is to use an algorithm stronger than SHA1. '.
962
		'Some platforms may consider weaker digest algorithms invalid', '<br/>');
963 b49f31d0 Sjon Hortensius
964 b35250d9 NewEraCracker
	$section->addInput(new Form_Input(
965
		'lifetime',
966 153c3aa6 Phil Davis
		'*Lifetime (days)',
967 b35250d9 NewEraCracker
		'number',
968 3a877e4a jim-p
		$pconfig['lifetime'],
969
		['max' => $max_lifetime]
970 3f0b7bc3 jim-p
	))->setHelp('The length of time the signed certificate will be valid, in days. %1$s' .
971 f944f4a7 jim-p
		'Server certificates should not have a lifetime over %2$s days or some platforms ' .
972
		'may consider the certificate invalid.', '<br/>', $cert_strict_values['max_server_cert_lifetime']);
973 b49f31d0 Sjon Hortensius
974 26e3967a jim-p
	$section->addInput(new Form_Input(
975
		'dn_commonname',
976
		'*Common Name',
977
		'text',
978
		$pconfig['dn_commonname'],
979
		['placeholder' => 'e.g. www.example.com']
980
	));
981
982
	$section->addInput(new Form_StaticText(
983
		null,
984
		gettext('The following certificate subject components are optional and may be left blank.')
985
	));
986
987 b49f31d0 Sjon Hortensius
	$section->addInput(new Form_Select(
988 b35250d9 NewEraCracker
		'dn_country',
989 80d50253 jim-p
		'Country Code',
990 b35250d9 NewEraCracker
		$pconfig['dn_country'],
991 232b1a69 Renato Botelho
		get_cert_country_codes()
992 b49f31d0 Sjon Hortensius
	));
993
994 b35250d9 NewEraCracker
	$section->addInput(new Form_Input(
995
		'dn_state',
996 80d50253 jim-p
		'State or Province',
997 b35250d9 NewEraCracker
		'text',
998
		$pconfig['dn_state'],
999
		['placeholder' => 'e.g. Texas']
1000 b49f31d0 Sjon Hortensius
	));
1001
1002 b35250d9 NewEraCracker
	$section->addInput(new Form_Input(
1003
		'dn_city',
1004 80d50253 jim-p
		'City',
1005 b35250d9 NewEraCracker
		'text',
1006
		$pconfig['dn_city'],
1007
		['placeholder' => 'e.g. Austin']
1008
	));
1009
1010
	$section->addInput(new Form_Input(
1011
		'dn_organization',
1012 80d50253 jim-p
		'Organization',
1013 b35250d9 NewEraCracker
		'text',
1014
		$pconfig['dn_organization'],
1015 da0f70ed jim-p
		['placeholder' => 'e.g. My Company Inc']
1016
	));
1017
1018
	$section->addInput(new Form_Input(
1019
		'dn_organizationalunit',
1020
		'Organizational Unit',
1021
		'text',
1022
		$pconfig['dn_organizationalunit'],
1023
		['placeholder' => 'e.g. My Department Name (optional)']
1024 b35250d9 NewEraCracker
	));
1025
1026
	$form->add($section);
1027
	$section = new Form_Section('External Signing Request');
1028
	$section->addClass('toggle-external collapse');
1029
1030 b49f31d0 Sjon Hortensius
	$section->addInput(new Form_Select(
1031 47c46bbd Viktor Gurov
		'csr_keytype',
1032
		'*Key type',
1033
		$pconfig['csr_keytype'],
1034
		array_combine($cert_keytypes, $cert_keytypes)
1035
	));
1036
1037 dace81a7 Viktor Gurov
	$group = new Form_Group($i == 0 ? '*Key length':'');
1038 e0f8d364 Viktor Gurov
	$group->addClass('csr_rsakeys');
1039 dace81a7 Viktor Gurov
	$group->add(new Form_Select(
1040 b35250d9 NewEraCracker
		'csr_keylen',
1041 dace81a7 Viktor Gurov
		null,
1042 b35250d9 NewEraCracker
		$pconfig['csr_keylen'],
1043
		array_combine($cert_keylens, $cert_keylens)
1044 3f0b7bc3 jim-p
	))->setHelp('The length to use when generating a new RSA key, in bits. %1$s' .
1045
		'The Key Length should not be lower than 2048 or some platforms ' .
1046
		'may consider the certificate invalid.', '<br/>');
1047 dace81a7 Viktor Gurov
	$section->add($group);
1048
1049 e0f8d364 Viktor Gurov
	$group = new Form_Group($i == 0 ? '*Elliptic Curve Name':'');
1050 2d13c7fc Viktor Gurov
	$group->addClass('csr_ecnames');
1051 dace81a7 Viktor Gurov
	$group->add(new Form_Select(
1052 e0f8d364 Viktor Gurov
		'csr_ecname',
1053 dace81a7 Viktor Gurov
		null,
1054 e0f8d364 Viktor Gurov
		$pconfig['csr_ecname'],
1055 cffcf9bf jim-p
		$openssl_ecnames
1056 dace81a7 Viktor Gurov
	));
1057
	$section->add($group);
1058 64cc39d3 Matthew Grooms
1059 b35250d9 NewEraCracker
	$section->addInput(new Form_Select(
1060
		'csr_digest_alg',
1061 153c3aa6 Phil Davis
		'*Digest Algorithm',
1062 b35250d9 NewEraCracker
		$pconfig['csr_digest_alg'],
1063
		array_combine($openssl_digest_algs, $openssl_digest_algs)
1064 3f0b7bc3 jim-p
	))->setHelp('The digest method used when the certificate is signed. %1$s' .
1065
		'The best practice is to use an algorithm stronger than SHA1. '.
1066
		'Some platforms may consider weaker digest algorithms invalid', '<br/>');
1067 b49f31d0 Sjon Hortensius
1068 26e3967a jim-p
	$section->addInput(new Form_Input(
1069
		'csr_dn_commonname',
1070
		'*Common Name',
1071
		'text',
1072
		$pconfig['csr_dn_commonname'],
1073
		['placeholder' => 'e.g. internal-ca']
1074
	));
1075
1076
	$section->addInput(new Form_StaticText(
1077
		null,
1078
		gettext('The following certificate subject components are optional and may be left blank.')
1079
	));
1080
1081 b35250d9 NewEraCracker
	$section->addInput(new Form_Select(
1082
		'csr_dn_country',
1083 80d50253 jim-p
		'Country Code',
1084 b35250d9 NewEraCracker
		$pconfig['csr_dn_country'],
1085 232b1a69 Renato Botelho
		get_cert_country_codes()
1086 b35250d9 NewEraCracker
	));
1087 bf9d50e8 Stephen Beaver
1088 b35250d9 NewEraCracker
	$section->addInput(new Form_Input(
1089
		'csr_dn_state',
1090 80d50253 jim-p
		'State or Province',
1091 b35250d9 NewEraCracker
		'text',
1092
		$pconfig['csr_dn_state'],
1093
		['placeholder' => 'e.g. Texas']
1094
	));
1095 bf9d50e8 Stephen Beaver
1096 b35250d9 NewEraCracker
	$section->addInput(new Form_Input(
1097
		'csr_dn_city',
1098 80d50253 jim-p
		'City',
1099 b35250d9 NewEraCracker
		'text',
1100
		$pconfig['csr_dn_city'],
1101
		['placeholder' => 'e.g. Austin']
1102
	));
1103 bf9d50e8 Stephen Beaver
1104 b35250d9 NewEraCracker
	$section->addInput(new Form_Input(
1105
		'csr_dn_organization',
1106 80d50253 jim-p
		'Organization',
1107 b35250d9 NewEraCracker
		'text',
1108
		$pconfig['csr_dn_organization'],
1109 da0f70ed jim-p
		['placeholder' => 'e.g. My Company Inc']
1110
	));
1111
1112
	$section->addInput(new Form_Input(
1113
		'csr_dn_organizationalunit',
1114
		'Organizational Unit',
1115
		'text',
1116
		$pconfig['csr_dn_organizationalunit'],
1117
		['placeholder' => 'e.g. My Department Name (optional)']
1118 b35250d9 NewEraCracker
	));
1119 b49f31d0 Sjon Hortensius
1120 0c82b8c2 jim-p
	$form->add($section);
1121
	$section = new Form_Section('Choose an Existing Certificate');
1122
	$section->addClass('toggle-existing collapse');
1123
1124
	$existCerts = array();
1125
1126 ca4456b9 jim-p
	foreach ($config['cert'] as $cert) {
1127
		if (!is_array($cert) || empty($cert)) {
1128
			continue;
1129
		}
1130 0c82b8c2 jim-p
		if (is_array($config['system']['user'][$userid]['cert'])) { // Could be MIA!
1131
			if (isset($userid) && in_array($cert['refid'], $config['system']['user'][$userid]['cert'])) {
1132
				continue;
1133
			}
1134
		}
1135
1136
		$ca = lookup_ca($cert['caref']);
1137
		if ($ca) {
1138
			$cert['descr'] .= " (CA: {$ca['descr']})";
1139
		}
1140
1141
		if (cert_in_use($cert['refid'])) {
1142
			$cert['descr'] .= " (In Use)";
1143
		}
1144
		if (is_cert_revoked($cert)) {
1145
			$cert['descr'] .= " (Revoked)";
1146
		}
1147
1148
		$existCerts[ $cert['refid'] ] = $cert['descr'];
1149
	}
1150
1151
	$section->addInput(new Form_Select(
1152
		'certref',
1153
		'*Existing Certificates',
1154
		$pconfig['certref'],
1155
		$existCerts
1156
	));
1157
1158
	$form->add($section);
1159
1160
	$section = new Form_Section('Certificate Attributes');
1161
	$section->addClass('toggle-external toggle-internal toggle-sign collapse');
1162
1163
	$section->addInput(new Form_StaticText(
1164
		gettext('Attribute Notes'),
1165
		'<span class="help-block">'.
1166
		gettext('The following attributes are added to certificates and ' .
1167
		'requests when they are created or signed. These attributes behave ' .
1168
		'differently depending on the selected mode.') .
1169
		'<br/><br/>' .
1170
		'<span class="toggle-internal collapse">' . gettext('For Internal Certificates, these attributes are added directly to the certificate as shown.') . '</span>' .
1171
		'<span class="toggle-external collapse">' .
1172
		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. ') .
1173
		'<br/><br/>' .
1174
		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>' .
1175
		'<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>' .
1176
		'</span>'
1177
	));
1178
1179
	$section->addInput(new Form_Select(
1180
		'type',
1181
		'*Certificate Type',
1182
		$pconfig['type'],
1183
		$cert_types
1184
	))->setHelp('Add type-specific usage attributes to the signed certificate.' .
1185
		' Used for placing usage restrictions on, or granting abilities to, ' .
1186
		'the signed certificate.');
1187
1188 282b6c66 jim-p
	if (empty($pconfig['altnames']['item'])) {
1189
		$pconfig['altnames']['item'] = array(
1190
			array('type' => null, 'value' => null)
1191
		);
1192
	}
1193
1194
	$counter = 0;
1195
	$numrows = count($pconfig['altnames']['item']) - 1;
1196
1197
	foreach ($pconfig['altnames']['item'] as $item) {
1198
1199
		$group = new Form_Group($counter == 0 ? 'Alternative Names':'');
1200
1201
		$group->add(new Form_Select(
1202
			'altname_type' . $counter,
1203
			'Type',
1204
			$item['type'],
1205
			$cert_altname_types
1206
		))->setHelp(($counter == $numrows) ? 'Type':null);
1207
1208
		$group->add(new Form_Input(
1209
			'altname_value' . $counter,
1210
			null,
1211
			'text',
1212
			$item['value']
1213
		))->setHelp(($counter == $numrows) ? 'Value':null);
1214
1215
		$group->add(new Form_Button(
1216
			'deleterow' . $counter,
1217
			'Delete',
1218
			null,
1219
			'fa-trash'
1220
		))->addClass('btn-warning');
1221
1222
		$group->addClass('repeatable');
1223
1224 0c82b8c2 jim-p
		$group->setHelp('Enter additional identifiers for the certificate ' .
1225
			'in this list. The Common Name field is automatically ' .
1226
			'added to the certificate as an Alternative Name. ' .
1227
			'The signing CA may ignore or change these values.');
1228 282b6c66 jim-p
1229
		$section->add($group);
1230
1231
		$counter++;
1232
	}
1233
1234
	$section->addInput(new Form_Button(
1235
		'addrow',
1236
		'Add',
1237
		null,
1238
		'fa-plus'
1239
	))->addClass('btn-success');
1240
1241 b35250d9 NewEraCracker
	$form->add($section);
1242 b49f31d0 Sjon Hortensius
1243 2e4372e3 Viktor G
	if (($act == 'edit') && !empty($pconfig['key'])) {
1244 96773352 jim-p
		$form->addGlobal(new Form_Button(
1245
			'exportpkey',
1246
			'Export Private Key',
1247
			null,
1248
			'fa-key'
1249
		))->addClass('btn-primary');
1250
		$form->addGlobal(new Form_Button(
1251
			'exportp12',
1252
			'Export PKCS#12',
1253
			null,
1254
			'fa-archive'
1255
		))->addClass('btn-primary');
1256
	}
1257 b49f31d0 Sjon Hortensius
1258 b35250d9 NewEraCracker
	print $form;
1259 64cc39d3 Matthew Grooms
1260 7e83055a jim-p
} elseif ($act == "csr" || (($_POST['save'] == gettext("Update")) && $input_errors)) {
1261 8f58b51b jim-p
	$form = new Form(false);
1262 308f0665 NewEraCracker
	$form->setAction('system_certmanager.php?act=csr');
1263 b29c322c Stephen Beaver
1264 5f88f964 k-paulius
	$section = new Form_Section("Complete Signing Request for " . $pconfig['descr']);
1265 b29c322c Stephen Beaver
1266 ba5c55e9 Stephen Beaver
	$section->addInput(new Form_Input(
1267
		'descr',
1268 153c3aa6 Phil Davis
		'*Descriptive name',
1269 ba5c55e9 Stephen Beaver
		'text',
1270
		$pconfig['descr']
1271
	));
1272
1273 b29c322c Stephen Beaver
	$section->addInput(new Form_Textarea(
1274
		'csr',
1275
		'Signing request data',
1276
		$pconfig['csr']
1277
	))->setReadonly()
1278 af28e231 Stephen Beaver
	  ->setWidth(7)
1279 813c6673 NOYB
	  ->setHelp('Copy the certificate signing data from here and forward it to a certificate authority for signing.');
1280 b29c322c Stephen Beaver
1281
	$section->addInput(new Form_Textarea(
1282
		'cert',
1283 153c3aa6 Phil Davis
		'*Final certificate data',
1284 b29c322c Stephen Beaver
		$pconfig['cert']
1285 af28e231 Stephen Beaver
	))->setWidth(7)
1286 813c6673 NOYB
	  ->setHelp('Paste the certificate received from the certificate authority here.');
1287 b29c322c Stephen Beaver
1288 f0b38e39 jim-p
	if (isset($id) && $thiscert) {
1289 ee12dd78 Peter Feichtinger
		$form->addGlobal(new Form_Input(
1290 b29c322c Stephen Beaver
			'id',
1291
			null,
1292
			'hidden',
1293
			$id
1294 ee12dd78 Peter Feichtinger
		));
1295 b29c322c Stephen Beaver
1296 ee12dd78 Peter Feichtinger
		$form->addGlobal(new Form_Input(
1297 b29c322c Stephen Beaver
			'act',
1298
			null,
1299
			'hidden',
1300
			'csr'
1301 ee12dd78 Peter Feichtinger
		));
1302
	}
1303 b29c322c Stephen Beaver
1304
	$form->add($section);
1305 8f58b51b jim-p
1306
	$form->addGlobal(new Form_Button(
1307 141d8913 jim-p
		'save',
1308 faab522f Renato Botelho
		'Update',
1309 8f58b51b jim-p
		null,
1310
		'fa-save'
1311
	))->addClass('btn-primary');
1312
1313 b29c322c Stephen Beaver
	print($form);
1314
} else {
1315
?>
1316 14973058 jim-p
<div class="panel panel-default" id="search-panel">
1317
	<div class="panel-heading">
1318
		<h2 class="panel-title">
1319
			<?=gettext('Search')?>
1320
			<span class="widget-heading-icon pull-right">
1321
				<a data-toggle="collapse" href="#search-panel_panel-body">
1322
					<i class="fa fa-plus-circle"></i>
1323
				</a>
1324
			</span>
1325
		</h2>
1326
	</div>
1327
	<div id="search-panel_panel-body" class="panel-body collapse in">
1328
		<div class="form-group">
1329
			<label class="col-sm-2 control-label">
1330
				<?=gettext("Search term")?>
1331
			</label>
1332
			<div class="col-sm-5"><input class="form-control" name="searchstr" id="searchstr" type="text"/></div>
1333
			<div class="col-sm-2">
1334
				<select id="where" class="form-control">
1335
					<option value="0"><?=gettext("Name")?></option>
1336
					<option value="1"><?=gettext("Distinguished Name")?></option>
1337
					<option value="2" selected><?=gettext("Both")?></option>
1338
				</select>
1339
			</div>
1340
			<div class="col-sm-3">
1341
				<a id="btnsearch" title="<?=gettext("Search")?>" class="btn btn-primary btn-sm"><i class="fa fa-search icon-embed-btn"></i><?=gettext("Search")?></a>
1342
				<a id="btnclear" title="<?=gettext("Clear")?>" class="btn btn-info btn-sm"><i class="fa fa-undo icon-embed-btn"></i><?=gettext("Clear")?></a>
1343
			</div>
1344
			<div class="col-sm-10 col-sm-offset-2">
1345 f30da999 jim-p
				<span class="help-block"><?=gettext('Enter a search string or *nix regular expression to search certificate names and distinguished names.')?></span>
1346 14973058 jim-p
			</div>
1347
		</div>
1348
	</div>
1349
</div>
1350 060ed238 Stephen Beaver
<div class="panel panel-default">
1351
	<div class="panel-heading"><h2 class="panel-title"><?=gettext('Certificates')?></h2></div>
1352
	<div class="panel-body">
1353
		<div class="table-responsive">
1354 14973058 jim-p
		<table class="table table-striped table-hover sortable-theme-bootstrap" data-sortable>
1355 060ed238 Stephen Beaver
			<thead>
1356
				<tr>
1357
					<th><?=gettext("Name")?></th>
1358
					<th><?=gettext("Issuer")?></th>
1359
					<th><?=gettext("Distinguished Name")?></th>
1360
					<th><?=gettext("In Use")?></th>
1361 4db1f211 Stephen Beaver
1362 060ed238 Stephen Beaver
					<th class="col-sm-2"><?=gettext("Actions")?></th>
1363
				</tr>
1364
			</thead>
1365
			<tbody>
1366 b29c322c Stephen Beaver
<?php
1367 4db1f211 Stephen Beaver
1368
$pluginparams = array();
1369
$pluginparams['type'] = 'certificates';
1370
$pluginparams['event'] = 'used_certificates';
1371
$certificates_used_by_packages = pkg_call_plugins('plugin_certificates', $pluginparams);
1372 46bd32bb Steve Beaver
foreach ($a_cert as $cert):
1373
	if (!is_array($cert) || empty($cert)) {
1374
		continue;
1375
	}
1376
	$name = htmlspecialchars($cert['descr']);
1377
	if ($cert['crt']) {
1378
		$subj = cert_get_subject($cert['crt']);
1379
		$issuer = cert_get_issuer($cert['crt']);
1380
		$purpose = cert_get_purpose($cert['crt']);
1381
1382
		if ($subj == $issuer) {
1383
			$caname = '<i>'. gettext("self-signed") .'</i>';
1384
		} else {
1385
			$caname = '<i>'. gettext("external").'</i>';
1386
		}
1387 b29c322c Stephen Beaver
1388 46bd32bb Steve Beaver
		$subj = htmlspecialchars(cert_escape_x509_chars($subj, true));
1389
	} else {
1390
		$subj = "";
1391
		$issuer = "";
1392
		$purpose = "";
1393
		$startdate = "";
1394
		$enddate = "";
1395
		$caname = "<em>" . gettext("private key only") . "</em>";
1396
	}
1397
1398
	if ($cert['csr']) {
1399
		$subj = htmlspecialchars(cert_escape_x509_chars(csr_get_subject($cert['csr']), true));
1400
		$caname = "<em>" . gettext("external - signature pending") . "</em>";
1401
	}
1402
1403
	$ca = lookup_ca($cert['caref']);
1404
	if ($ca) {
1405
		$caname = $ca['descr'];
1406
	}
1407 b29c322c Stephen Beaver
?>
1408 060ed238 Stephen Beaver
				<tr>
1409 46bd32bb Steve Beaver
					<td>
1410
						<?=$name?><br />
1411
						<?php if ($cert['type']): ?>
1412
							<i><?=$cert_types[$cert['type']]?></i><br />
1413
						<?php endif?>
1414
						<?php if (is_array($purpose)): ?>
1415
							CA: <b><?=$purpose['ca']?></b><br/>
1416
							<?=gettext("Server")?>: <b><?=$purpose['server']?></b><br/>
1417
						<?php endif?>
1418
					</td>
1419
					<td><?=$caname?></td>
1420
					<td>
1421
						<?=$subj?>
1422
						<?= cert_print_infoblock($cert); ?>
1423
						<?php cert_print_dates($cert);?>
1424
					</td>
1425
					<td>
1426
						<?php if (is_cert_revoked($cert)): ?>
1427
							<i><?=gettext("Revoked")?></i>
1428
						<?php endif?>
1429
						<?php if (is_webgui_cert($cert['refid'])): ?>
1430
							<?=gettext("webConfigurator")?>
1431
						<?php endif?>
1432
						<?php if (is_user_cert($cert['refid'])): ?>
1433
							<?=gettext("User Cert")?>
1434
						<?php endif?>
1435
						<?php if (is_openvpn_server_cert($cert['refid'])): ?>
1436
							<?=gettext("OpenVPN Server")?>
1437
						<?php endif?>
1438
						<?php if (is_openvpn_client_cert($cert['refid'])): ?>
1439
							<?=gettext("OpenVPN Client")?>
1440
						<?php endif?>
1441
						<?php if (is_ipsec_cert($cert['refid'])): ?>
1442
							<?=gettext("IPsec Tunnel")?>
1443
						<?php endif?>
1444
						<?php if (is_captiveportal_cert($cert['refid'])): ?>
1445
							<?=gettext("Captive Portal")?>
1446
						<?php endif?>
1447
						<?php if (is_unbound_cert($cert['refid'])): ?>
1448
							<?=gettext("DNS Resolver")?>
1449
						<?php endif?>
1450
						<?php echo cert_usedby_description($cert['refid'], $certificates_used_by_packages); ?>
1451 060ed238 Stephen Beaver
					</td>
1452
					<td>
1453
						<?php if (!$cert['csr']): ?>
1454 96773352 jim-p
							<a href="system_certmanager.php?act=edit&amp;id=<?=$cert['refid']?>" class="fa fa-pencil" title="<?=gettext("Edit Certificate")?>"></a>
1455 f0b38e39 jim-p
							<a href="system_certmanager.php?act=exp&amp;id=<?=$cert['refid']?>" class="fa fa-certificate" title="<?=gettext("Export Certificate")?>"></a>
1456 4594038a Steve Beaver
							<?php if ($cert['prv']): ?>
1457 f0b38e39 jim-p
								<a href="system_certmanager.php?act=key&amp;id=<?=$cert['refid']?>" class="fa fa-key" title="<?=gettext("Export Key")?>"></a>
1458 d5137a93 Viktor G
								<a href="system_certmanager.php?act=p12&amp;id=<?=$cert['refid']?>" class="fa fa-archive" title="<?=gettext("Export P12")?>"></a>
1459 4594038a Steve Beaver
							<?php endif?>
1460 03a84081 jim-p
							<?php if (is_cert_locally_renewable($cert)): ?>
1461
								<a href="system_certmanager_renew.php?type=cert&amp;refid=<?=$cert['refid']?>" class="fa fa-repeat" title="<?=gettext("Reissue/Renew")?>"></a>
1462 2e4372e3 Viktor G
							<?php endif ?>
1463 060ed238 Stephen Beaver
						<?php else: ?>
1464 f0b38e39 jim-p
							<a href="system_certmanager.php?act=csr&amp;id=<?=$cert['refid']?>" class="fa fa-pencil" title="<?=gettext("Update CSR")?>"></a>
1465
							<a href="system_certmanager.php?act=req&amp;id=<?=$cert['refid']?>" class="fa fa-sign-in" title="<?=gettext("Export Request")?>"></a>
1466
							<a href="system_certmanager.php?act=key&amp;id=<?=$cert['refid']?>" class="fa fa-key" title="<?=gettext("Export Key")?>"></a>
1467 060ed238 Stephen Beaver
						<?php endif?>
1468
						<?php if (!cert_in_use($cert['refid'])): ?>
1469 f0b38e39 jim-p
							<a href="system_certmanager.php?act=del&amp;id=<?=$cert['refid']?>" class="fa fa-trash" title="<?=gettext("Delete Certificate")?>" usepost></a>
1470 060ed238 Stephen Beaver
						<?php endif?>
1471
					</td>
1472
				</tr>
1473 4db1f211 Stephen Beaver
<?php
1474
	endforeach; ?>
1475 060ed238 Stephen Beaver
			</tbody>
1476
		</table>
1477
		</div>
1478
	</div>
1479 b29c322c Stephen Beaver
</div>
1480
1481
<nav class="action-buttons">
1482 4611e283 Steve Beaver
	<a href="?act=new" class="btn btn-success btn-sm">
1483 b29c322c Stephen Beaver
		<i class="fa fa-plus icon-embed-btn"></i>
1484 2052d3e2 Steve Beaver
		<?=gettext("Add/Sign")?>
1485 b29c322c Stephen Beaver
	</a>
1486
</nav>
1487 14973058 jim-p
<script type="text/javascript">
1488
//<![CDATA[
1489
1490
events.push(function() {
1491
1492
	// Make these controls plain buttons
1493
	$("#btnsearch").prop('type', 'button');
1494
	$("#btnclear").prop('type', 'button');
1495
1496
	// Search for a term in the entry name and/or dn
1497
	$("#btnsearch").click(function() {
1498
		var searchstr = $('#searchstr').val().toLowerCase();
1499
		var table = $("table tbody");
1500
		var where = $('#where').val();
1501
1502
		table.find('tr').each(function (i) {
1503
			var $tds = $(this).find('td'),
1504
				shortname = $tds.eq(0).text().trim().toLowerCase(),
1505
				dn = $tds.eq(2).text().trim().toLowerCase();
1506
1507
			regexp = new RegExp(searchstr);
1508
			if (searchstr.length > 0) {
1509
				if (!(regexp.test(shortname) && (where != 1)) && !(regexp.test(dn) && (where != 0))) {
1510
					$(this).hide();
1511
				} else {
1512
					$(this).show();
1513
				}
1514
			} else {
1515
				$(this).show();	// A blank search string shows all
1516
			}
1517
		});
1518
	});
1519
1520
	// Clear the search term and unhide all rows (that were hidden during a previous search)
1521
	$("#btnclear").click(function() {
1522
		var table = $("table tbody");
1523
1524
		$('#searchstr').val("");
1525
1526
		table.find('tr').each(function (i) {
1527
			$(this).show();
1528
		});
1529
	});
1530
1531
	// Hitting the enter key will do the same as clicking the search button
1532
	$("#searchstr").on("keyup", function (event) {
1533
		if (event.keyCode == 13) {
1534
			$("#btnsearch").get(0).click();
1535
		}
1536
	});
1537
});
1538
//]]>
1539
</script>
1540 e9258698 NewEraCracker
<?php
1541 b29c322c Stephen Beaver
	include("foot.inc");
1542
	exit;
1543
}
1544
1545
1546 51583438 Stephen Beaver
?>
1547 8fd9052f Colin Fleming
<script type="text/javascript">
1548 51583438 Stephen Beaver
//<![CDATA[
1549 78863416 Phil Davis
events.push(function() {
1550 bf9d50e8 Stephen Beaver
1551 96d78012 Viktor Gurov
	$('.import_type_toggle').click(function() {
1552
		var x509 = (this.value === 'x509');
1553
		hideInput('cert', !x509);
1554
		setRequired('cert', x509);
1555
		hideInput('key', !x509);
1556
		setRequired('key', x509);
1557
		hideInput('pkcs12_cert', x509);
1558
		setRequired('pkcs12_cert', !x509);
1559
		hideInput('pkcs12_pass', x509);
1560
		hideCheckbox('pkcs12_intermediate', x509);
1561
	});
1562
	if ($('input[name=import_type]:checked').val() == 'x509') {
1563
		hideInput('pkcs12_cert', true);
1564
		setRequired('pkcs12_cert', false);
1565
		hideInput('pkcs12_pass', true);
1566
		hideCheckbox('pkcs12_intermediate', true);
1567
		hideInput('cert', false);
1568
		setRequired('cert', true);
1569
		hideInput('key', false);
1570
		setRequired('key', true);
1571 e7e4ba5a Viktor G
	} else if ($('input[name=import_type]:checked').val() == 'pkcs12') {
1572 96d78012 Viktor Gurov
		hideInput('cert', true);
1573
		setRequired('cert', false);
1574
		hideInput('key', true);
1575
		setRequired('key', false);
1576
		setRequired('pkcs12_cert', false);
1577
	}
1578
1579 51583438 Stephen Beaver
<?php if ($internal_ca_count): ?>
1580
	function internalca_change() {
1581
1582
		caref = $('#caref').val();
1583
1584
		switch (caref) {
1585
<?php
1586
			foreach ($a_ca as $ca):
1587
				if (!$ca['prv']) {
1588
					continue;
1589
				}
1590
1591 746c9afc jim-p
				$subject = @cert_get_subject_hash($ca['crt']);
1592
				if (!is_array($subject) || empty($subject)) {
1593
					continue;
1594
				}
1595 51583438 Stephen Beaver
?>
1596
				case "<?=$ca['refid'];?>":
1597 1ec79365 jim-p
					$('#dn_country').val(<?=json_encode(cert_escape_x509_chars($subject['C'], true));?>);
1598
					$('#dn_state').val(<?=json_encode(cert_escape_x509_chars($subject['ST'], true));?>);
1599
					$('#dn_city').val(<?=json_encode(cert_escape_x509_chars($subject['L'], true));?>);
1600
					$('#dn_organization').val(<?=json_encode(cert_escape_x509_chars($subject['O'], true));?>);
1601
					$('#dn_organizationalunit').val(<?=json_encode(cert_escape_x509_chars($subject['OU'], true));?>);
1602 51583438 Stephen Beaver
					break;
1603
<?php
1604
			endforeach;
1605
?>
1606
		}
1607
	}
1608
1609 2052d3e2 Steve Beaver
	function set_csr_ro() {
1610 b078cd59 Steve Beaver
		var newcsr = ($('#csrtosign').val() == "new");
1611 65d735f0 Steve Beaver
1612
		$('#csrpaste').attr('readonly', !newcsr);
1613 55047259 Steve Beaver
		$('#keypaste').attr('readonly', !newcsr);
1614 65d735f0 Steve Beaver
		setRequired('csrpaste', newcsr);
1615 2052d3e2 Steve Beaver
	}
1616
1617 3f0b7bc3 jim-p
	function check_lifetime() {
1618
		var maxserverlife = <?= $cert_strict_values['max_server_cert_lifetime'] ?>;
1619
		var ltid = '#lifetime';
1620
		if ($('#method').val() == "sign") {
1621
			ltid = '#csrsign_lifetime';
1622
		}
1623
		if (($('#type').val() == "server") && (parseInt($(ltid).val()) > maxserverlife)) {
1624
			$(ltid).parent().parent().removeClass("text-normal").addClass("text-warning");
1625
			$(ltid).removeClass("text-normal").addClass("text-warning");
1626
		} else {
1627
			$(ltid).parent().parent().removeClass("text-warning").addClass("text-normal");
1628
			$(ltid).removeClass("text-warning").addClass("text-normal");
1629
		}
1630
	}
1631
	function check_keylen() {
1632
		var min_keylen = <?= $cert_strict_values['min_private_key_bits'] ?>;
1633
		var klid = '#keylen';
1634
		if ($('#method').val() == "external") {
1635
			klid = '#csr_keylen';
1636
		}
1637
		/* Color the Parent/Label */
1638
		if (parseInt($(klid).val()) < min_keylen) {
1639
			$(klid).parent().parent().removeClass("text-normal").addClass("text-warning");
1640
		} else {
1641
			$(klid).parent().parent().removeClass("text-warning").addClass("text-normal");
1642
		}
1643
		/* Color individual options */
1644
		$(klid + " option").filter(function() {
1645
			return parseInt($(this).val()) < min_keylen;
1646
		}).removeClass("text-normal").addClass("text-warning").siblings().removeClass("text-warning").addClass("text-normal");
1647
	}
1648
1649
	function check_digest() {
1650
		var weak_algs = <?= json_encode($cert_strict_values['digest_blacklist']) ?>;
1651
		var daid = '#digest_alg';
1652
		if ($('#method').val() == "external") {
1653
			daid = '#csr_digest_alg';
1654
		} else if ($('#method').val() == "sign") {
1655
			daid = '#csrsign_digest_alg';
1656
		}
1657
		/* Color the Parent/Label */
1658
		if (jQuery.inArray($(daid).val(), weak_algs) > -1) {
1659
			$(daid).parent().parent().removeClass("text-normal").addClass("text-warning");
1660
		} else {
1661
			$(daid).parent().parent().removeClass("text-warning").addClass("text-normal");
1662
		}
1663
		/* Color individual options */
1664
		$(daid + " option").filter(function() {
1665
			return (jQuery.inArray($(this).val(), weak_algs) > -1);
1666
		}).removeClass("text-normal").addClass("text-warning").siblings().removeClass("text-warning").addClass("text-normal");
1667
	}
1668
1669 eef93144 Jared Dillard
	// ---------- Click checkbox handlers ---------------------------------------------------------
1670 f74457df Stephen Beaver
1671 3f0b7bc3 jim-p
	$('#type').on('change', function() {
1672
		check_lifetime();
1673
	});
1674
	$('#method').on('change', function() {
1675
		check_lifetime();
1676
		check_keylen();
1677
		check_digest();
1678
	});
1679
	$('#lifetime').on('change', function() {
1680
		check_lifetime();
1681
	});
1682
	$('#csrsign_lifetime').on('change', function() {
1683
		check_lifetime();
1684
	});
1685
1686
	$('#keylen').on('change', function() {
1687
		check_keylen();
1688
	});
1689
	$('#csr_keylen').on('change', function() {
1690
		check_keylen();
1691
	});
1692
1693
	$('#digest_alg').on('change', function() {
1694
		check_digest();
1695
	});
1696
	$('#csr_digest_alg').on('change', function() {
1697
		check_digest();
1698
	});
1699
1700 51583438 Stephen Beaver
	$('#caref').on('change', function() {
1701
		internalca_change();
1702
	});
1703
1704 2052d3e2 Steve Beaver
	$('#csrtosign').change(function () {
1705
		set_csr_ro();
1706
	});
1707
1708 dace81a7 Viktor Gurov
	function change_keytype() {
1709 e655d548 jim-p
		hideClass('rsakeys', ($('#keytype').val() != 'RSA'));
1710
		hideClass('ecnames', ($('#keytype').val() != 'ECDSA'));
1711
	}
1712 dace81a7 Viktor Gurov
1713
	$('#keytype').change(function () {
1714 e655d548 jim-p
		change_keytype();
1715
	});
1716 dace81a7 Viktor Gurov
1717
	function change_csrkeytype() {
1718 e655d548 jim-p
		hideClass('csr_rsakeys', ($('#csr_keytype').val() != 'RSA'));
1719
		hideClass('csr_ecnames', ($('#csr_keytype').val() != 'ECDSA'));
1720
	}
1721 dace81a7 Viktor Gurov
1722
	$('#csr_keytype').change(function () {
1723 e655d548 jim-p
		change_csrkeytype();
1724
	});
1725 dace81a7 Viktor Gurov
1726 eef93144 Jared Dillard
	// ---------- On initial page load ------------------------------------------------------------
1727
1728 51583438 Stephen Beaver
	internalca_change();
1729 2052d3e2 Steve Beaver
	set_csr_ro();
1730 dace81a7 Viktor Gurov
	change_keytype();
1731
	change_csrkeytype();
1732 3f0b7bc3 jim-p
	check_lifetime();
1733
	check_keylen();
1734
	check_digest();
1735 51583438 Stephen Beaver
1736 0bc61baa Stephen Beaver
	// Suppress "Delete row" button if there are fewer than two rows
1737
	checkLastRow();
1738
1739 dace81a7 Viktor Gurov
1740 51583438 Stephen Beaver
<?php endif; ?>
1741
1742
1743
});
1744
//]]>
1745
</script>
1746
<?php
1747 0edcccc3 Daniel Seebald
include('foot.inc');