Project

General

Profile

Download (39.3 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 b8f91b7c Luiz Souza
 * Copyright (c) 2004-2018 Rubicon Communications, LLC (Netgate)
7 c5d81585 Renato Botelho
 * Copyright (c) 2008 Shrew Soft Inc
8
 * All rights reserved.
9 98402844 Stephen Beaver
 *
10 b12ea3fb Renato Botelho
 * Licensed under the Apache License, Version 2.0 (the "License");
11
 * you may not use this file except in compliance with the License.
12
 * You may obtain a copy of the License at
13 98402844 Stephen Beaver
 *
14 b12ea3fb Renato Botelho
 * http://www.apache.org/licenses/LICENSE-2.0
15 98402844 Stephen Beaver
 *
16 b12ea3fb Renato Botelho
 * Unless required by applicable law or agreed to in writing, software
17
 * distributed under the License is distributed on an "AS IS" BASIS,
18
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19
 * See the License for the specific language governing permissions and
20
 * limitations under the License.
21 98402844 Stephen Beaver
 */
22 64cc39d3 Matthew Grooms
23
##|+PRIV
24
##|*IDENT=page-system-certmanager
25
##|*NAME=System: Certificate Manager
26
##|*DESCR=Allow access to the 'System: Certificate Manager' page.
27
##|*MATCH=system_certmanager.php*
28
##|-PRIV
29
30 c81ef6e2 Phil Davis
require_once("guiconfig.inc");
31 14f5ae08 Ermal Lu?i
require_once("certs.inc");
32 fdd8fafc doktornotor
require_once("pfsense-utils.inc");
33 64cc39d3 Matthew Grooms
34
$cert_methods = array(
35 ad9b5c67 jim-p
	"import" => gettext("Import an existing Certificate"),
36 a37753d7 Vinicius Coque
	"internal" => gettext("Create an internal Certificate"),
37 ad9b5c67 jim-p
	"external" => gettext("Create a Certificate Signing Request"),
38 2052d3e2 Steve Beaver
	"sign" => gettext("Sign a Certificate Signing Request")
39 ad9b5c67 jim-p
);
40 64cc39d3 Matthew Grooms
41 5065aa44 stilez
$cert_keylens = array("512", "1024", "2048", "3072", "4096", "7680", "8192", "15360", "16384");
42 56b1ed39 Phil Davis
$cert_types = array(
43
	"server" => "Server Certificate",
44
	"user" => "User Certificate");
45 64cc39d3 Matthew Grooms
46 2e1809dd jim-p
global $cert_altname_types;
47 84141846 jim-p
global $openssl_digest_algs;
48 2f65de89 jim-p
49 12e3e735 jim-p
if (isset($_REQUEST['userid']) && is_numericint($_REQUEST['userid'])) {
50 4611e283 Steve Beaver
	$userid = $_REQUEST['userid'];
51 56b1ed39 Phil Davis
}
52 e41ec584 Renato Botelho
53
if (isset($userid)) {
54 ad9b5c67 jim-p
	$cert_methods["existing"] = gettext("Choose an existing certificate");
55 56b1ed39 Phil Davis
	if (!is_array($config['system']['user'])) {
56 ad9b5c67 jim-p
		$config['system']['user'] = array();
57 56b1ed39 Phil Davis
	}
58 ad9b5c67 jim-p
	$a_user =& $config['system']['user'];
59
}
60
61 4611e283 Steve Beaver
if (isset($_REQUEST['id']) && is_numericint($_REQUEST['id'])) {
62
	$id = $_REQUEST['id'];
63 56b1ed39 Phil Davis
}
64 64cc39d3 Matthew Grooms
65 56b1ed39 Phil Davis
if (!is_array($config['ca'])) {
66 b4e6524c jim-p
	$config['ca'] = array();
67 56b1ed39 Phil Davis
}
68 64cc39d3 Matthew Grooms
69 b4e6524c jim-p
$a_ca =& $config['ca'];
70 64cc39d3 Matthew Grooms
71 56b1ed39 Phil Davis
if (!is_array($config['cert'])) {
72 b4e6524c jim-p
	$config['cert'] = array();
73 56b1ed39 Phil Davis
}
74 64cc39d3 Matthew Grooms
75 b4e6524c jim-p
$a_cert =& $config['cert'];
76 64cc39d3 Matthew Grooms
77
$internal_ca_count = 0;
78 56b1ed39 Phil Davis
foreach ($a_ca as $ca) {
79
	if ($ca['prv']) {
80 64cc39d3 Matthew Grooms
		$internal_ca_count++;
81 56b1ed39 Phil Davis
	}
82
}
83 64cc39d3 Matthew Grooms
84 4611e283 Steve Beaver
$act = $_REQUEST['act'];
85 8b35eae5 Stephen Beaver
86 4611e283 Steve Beaver
if ($_POST['act'] == "del") {
87 64cc39d3 Matthew Grooms
88 40e6086a jim-p
	if (!isset($a_cert[$id])) {
89 64cc39d3 Matthew Grooms
		pfSenseHeader("system_certmanager.php");
90
		exit;
91
	}
92
93
	unset($a_cert[$id]);
94
	write_config();
95 8545adde k-paulius
	$savemsg = sprintf(gettext("Certificate %s successfully deleted."), htmlspecialchars($a_cert[$id]['descr']));
96 2f51259b jim-p
	pfSenseHeader("system_certmanager.php");
97
	exit;
98 64cc39d3 Matthew Grooms
}
99
100
if ($act == "new") {
101 e8afd822 Steve Beaver
	$pconfig['method'] = $_POST['method'];
102 64cc39d3 Matthew Grooms
	$pconfig['keylen'] = "2048";
103 28a20fdb jim-p
	$pconfig['digest_alg'] = "sha256";
104 8f07b51c PiBa-NL
	$pconfig['csr_keylen'] = "2048";
105
	$pconfig['csr_digest_alg'] = "sha256";
106 aec3a259 jim-p
	$pconfig['csrsign_digest_alg'] = "sha256";
107 7aaabd69 jim-p
	$pconfig['type'] = "user";
108 cf360495 Chris Buechler
	$pconfig['lifetime'] = "3650";
109 64cc39d3 Matthew Grooms
}
110
111 93823b10 Matthew Grooms
if ($act == "exp") {
112
113
	if (!$a_cert[$id]) {
114
		pfSenseHeader("system_certmanager.php");
115
		exit;
116
	}
117
118 f2a86ca9 jim-p
	$exp_name = urlencode("{$a_cert[$id]['descr']}.crt");
119 93823b10 Matthew Grooms
	$exp_data = base64_decode($a_cert[$id]['crt']);
120
	$exp_size = strlen($exp_data);
121
122
	header("Content-Type: application/octet-stream");
123
	header("Content-Disposition: attachment; filename={$exp_name}");
124
	header("Content-Length: $exp_size");
125
	echo $exp_data;
126
	exit;
127
}
128
129 53f5b15f jim-p
if ($act == "req") {
130
131
	if (!$a_cert[$id]) {
132
		pfSenseHeader("system_certmanager.php");
133
		exit;
134
	}
135
136
	$exp_name = urlencode("{$a_cert[$id]['descr']}.req");
137
	$exp_data = base64_decode($a_cert[$id]['csr']);
138
	$exp_size = strlen($exp_data);
139
140
	header("Content-Type: application/octet-stream");
141
	header("Content-Disposition: attachment; filename={$exp_name}");
142
	header("Content-Length: $exp_size");
143
	echo $exp_data;
144
	exit;
145
}
146
147 73fbece8 mgrooms
if ($act == "key") {
148
149
	if (!$a_cert[$id]) {
150
		pfSenseHeader("system_certmanager.php");
151
		exit;
152
	}
153
154 f2a86ca9 jim-p
	$exp_name = urlencode("{$a_cert[$id]['descr']}.key");
155 73fbece8 mgrooms
	$exp_data = base64_decode($a_cert[$id]['prv']);
156
	$exp_size = strlen($exp_data);
157
158
	header("Content-Type: application/octet-stream");
159
	header("Content-Disposition: attachment; filename={$exp_name}");
160
	header("Content-Length: $exp_size");
161
	echo $exp_data;
162
	exit;
163
}
164
165 eaf23c17 jim-p
if ($act == "p12") {
166
	if (!$a_cert[$id]) {
167
		pfSenseHeader("system_certmanager.php");
168
		exit;
169
	}
170
171
	$exp_name = urlencode("{$a_cert[$id]['descr']}.p12");
172 eed5b507 jim-p
	$args = array();
173
	$args['friendly_name'] = $a_cert[$id]['descr'];
174
175
	$ca = lookup_ca($a_cert[$id]['caref']);
176 2052d3e2 Steve Beaver
177 56b1ed39 Phil Davis
	if ($ca) {
178 eed5b507 jim-p
		$args['extracerts'] = openssl_x509_read(base64_decode($ca['crt']));
179 56b1ed39 Phil Davis
	}
180 eaf23c17 jim-p
181
	$res_crt = openssl_x509_read(base64_decode($a_cert[$id]['crt']));
182
	$res_key = openssl_pkey_get_private(array(0 => base64_decode($a_cert[$id]['prv']) , 1 => ""));
183
184
	$exp_data = "";
185 eed5b507 jim-p
	openssl_pkcs12_export($res_crt, $exp_data, $res_key, null, $args);
186 eaf23c17 jim-p
	$exp_size = strlen($exp_data);
187
188
	header("Content-Type: application/octet-stream");
189
	header("Content-Disposition: attachment; filename={$exp_name}");
190
	header("Content-Length: $exp_size");
191
	echo $exp_data;
192
	exit;
193
}
194
195 64cc39d3 Matthew Grooms
if ($act == "csr") {
196
	if (!$a_cert[$id]) {
197
		pfSenseHeader("system_certmanager.php");
198
		exit;
199
	}
200
201 f2a86ca9 jim-p
	$pconfig['descr'] = $a_cert[$id]['descr'];
202 64cc39d3 Matthew Grooms
	$pconfig['csr'] = base64_decode($a_cert[$id]['csr']);
203
}
204
205 4611e283 Steve Beaver
if ($_POST['save']) {
206 0edcccc3 Daniel Seebald
207 e64aa6f8 Carlos Eduardo Ramos
	if ($_POST['save'] == gettext("Save")) {
208 21cc2faa Evgeny Yurchenko
		$input_errors = array();
209 64cc39d3 Matthew Grooms
		$pconfig = $_POST;
210
211
		/* input validation */
212 2052d3e2 Steve Beaver
		if ($pconfig['method'] == "sign") {
213
			$reqdfields = explode(" ",
214
				"descr catosignwith");
215
			$reqdfieldsn = array(
216
				gettext("Descriptive name"),
217
				gettext("CA to sign with"));
218
219 7db12011 jim-p
			if (($_POST['csrtosign'] === "new") &&
220
			    ((!strstr($_POST['csrpaste'], "BEGIN CERTIFICATE REQUEST") || !strstr($_POST['csrpaste'], "END CERTIFICATE REQUEST")) &&
221
			    (!strstr($_POST['csrpaste'], "BEGIN NEW CERTIFICATE REQUEST") || !strstr($_POST['csrpaste'], "END NEW CERTIFICATE REQUEST")))) {
222 2052d3e2 Steve Beaver
				$input_errors[] = gettext("This signing request does not appear to be valid.");
223
			}
224 55047259 Steve Beaver
225
			if ( (($_POST['csrtosign'] === "new") && (strlen($_POST['keypaste']) > 0)) && (!strstr($_POST['keypaste'], "BEGIN PRIVATE KEY") || !strstr($_POST['keypaste'], "END PRIVATE KEY"))) {
226
				$input_errors[] = gettext("This private does not appear to be valid.");
227
				$input_errors[] = gettext("Key data field should be blank, or a valid x509 private key");
228
			}
229
230 2052d3e2 Steve Beaver
		}
231
232 ad9b5c67 jim-p
		if ($pconfig['method'] == "import") {
233 64cc39d3 Matthew Grooms
			$reqdfields = explode(" ",
234 56b1ed39 Phil Davis
				"descr cert key");
235 38fb1109 Vinicius Coque
			$reqdfieldsn = array(
236 56b1ed39 Phil Davis
				gettext("Descriptive name"),
237
				gettext("Certificate data"),
238
				gettext("Key data"));
239
			if ($_POST['cert'] && (!strstr($_POST['cert'], "BEGIN CERTIFICATE") || !strstr($_POST['cert'], "END CERTIFICATE"))) {
240 396cfe2e jim-p
				$input_errors[] = gettext("This certificate does not appear to be valid.");
241 56b1ed39 Phil Davis
			}
242 55047259 Steve Beaver
243 1746c5ce PiBa-NL
			if (cert_get_publickey($_POST['cert'], false) != cert_get_publickey($_POST['key'], false, 'prv')) {
244 2cf5db21 jim-p
				$input_errors[] = gettext("The submitted private key does not match the submitted certificate data.");
245
			}
246 64cc39d3 Matthew Grooms
		}
247
248
		if ($pconfig['method'] == "internal") {
249
			$reqdfields = explode(" ",
250 56b1ed39 Phil Davis
				"descr caref keylen type lifetime dn_country dn_state dn_city ".
251
				"dn_organization dn_email dn_commonname");
252 38fb1109 Vinicius Coque
			$reqdfieldsn = array(
253 56b1ed39 Phil Davis
				gettext("Descriptive name"),
254
				gettext("Certificate authority"),
255
				gettext("Key length"),
256
				gettext("Certificate Type"),
257
				gettext("Lifetime"),
258
				gettext("Distinguished name Country Code"),
259
				gettext("Distinguished name State or Province"),
260
				gettext("Distinguished name City"),
261
				gettext("Distinguished name Organization"),
262
				gettext("Distinguished name Email Address"),
263
				gettext("Distinguished name Common Name"));
264 64cc39d3 Matthew Grooms
		}
265
266
		if ($pconfig['method'] == "external") {
267
			$reqdfields = explode(" ",
268 56b1ed39 Phil Davis
				"descr csr_keylen csr_dn_country csr_dn_state csr_dn_city ".
269
				"csr_dn_organization csr_dn_email csr_dn_commonname");
270 38fb1109 Vinicius Coque
			$reqdfieldsn = array(
271 56b1ed39 Phil Davis
				gettext("Descriptive name"),
272
				gettext("Key length"),
273
				gettext("Distinguished name Country Code"),
274
				gettext("Distinguished name State or Province"),
275
				gettext("Distinguished name City"),
276
				gettext("Distinguished name Organization"),
277
				gettext("Distinguished name Email Address"),
278
				gettext("Distinguished name Common Name"));
279 64cc39d3 Matthew Grooms
		}
280
281 ad9b5c67 jim-p
		if ($pconfig['method'] == "existing") {
282
			$reqdfields = array("certref");
283
			$reqdfieldsn = array(gettext("Existing Certificate Choice"));
284
		}
285
286 547c56c4 jim-p
		$altnames = array();
287 1e9b4611 Renato Botelho
		do_input_validation($_POST, $reqdfields, $reqdfieldsn, $input_errors);
288 2052d3e2 Steve Beaver
289 eecbeec4 Renato Botelho
		if ($pconfig['method'] != "import" && $pconfig['method'] != "existing") {
290 2f65de89 jim-p
			/* subjectAltNames */
291 0c82b8c2 jim-p
			$san_typevar = 'altname_type';
292
			$san_valuevar = 'altname_value';
293
			// This is just the blank alternate name that is added for display purposes. We don't want to validate/save it
294
			if ($_POST["{$san_valuevar}0"] == "") {
295
				unset($_POST["{$san_typevar}0"]);
296
				unset($_POST["{$san_valuevar}0"]);
297
			}
298 bf9d50e8 Stephen Beaver
			foreach ($_POST as $key => $value) {
299
				$entry = '';
300 0c82b8c2 jim-p
				if (!substr_compare($san_typevar, $key, 0, strlen($san_typevar))) {
301
					$entry = substr($key, strlen($san_typevar));
302 bf9d50e8 Stephen Beaver
					$field = 'type';
303 0c82b8c2 jim-p
				} elseif (!substr_compare($san_valuevar, $key, 0, strlen($san_valuevar))) {
304
					$entry = substr($key, strlen($san_valuevar));
305 bf9d50e8 Stephen Beaver
					$field = 'value';
306
				}
307
308
				if (ctype_digit($entry)) {
309 3f0efd58 Stephen Beaver
					$entry++;	// Pre-bootstrap code is one-indexed, but the bootstrap code is 0-indexed
310 bf9d50e8 Stephen Beaver
					$altnames[$entry][$field] = $value;
311
				}
312 2f65de89 jim-p
			}
313 bf9d50e8 Stephen Beaver
314 edf37d56 Renato Botelho
			$pconfig['altnames']['item'] = $altnames;
315 2f65de89 jim-p
316
			/* Input validation for subjectAltNames */
317
			foreach ($altnames as $idx => $altname) {
318
				switch ($altname['type']) {
319
					case "DNS":
320 19a1cf34 jim-p
						if (!is_hostname($altname['value'], true) || is_ipaddr($altname['value'])) {
321 0edcccc3 Daniel Seebald
							array_push($input_errors, "DNS subjectAltName values must be valid hostnames, FQDNs or wildcard domains.");
322 56b1ed39 Phil Davis
						}
323 2f65de89 jim-p
						break;
324
					case "IP":
325 56b1ed39 Phil Davis
						if (!is_ipaddr($altname['value'])) {
326 2f65de89 jim-p
							array_push($input_errors, "IP subjectAltName values must be valid IP Addresses");
327 56b1ed39 Phil Davis
						}
328 2f65de89 jim-p
						break;
329
					case "email":
330 56b1ed39 Phil Davis
						if (empty($altname['value'])) {
331 813c6673 NOYB
							array_push($input_errors, "An e-mail address must be provided for this type of subjectAltName");
332 56b1ed39 Phil Davis
						}
333
						if (preg_match("/[\!\#\$\%\^\(\)\~\?\>\<\&\/\\\,\"\']/", $altname['value'])) {
334 2f65de89 jim-p
							array_push($input_errors, "The e-mail provided in a subjectAltName contains invalid characters.");
335 56b1ed39 Phil Davis
						}
336 2f65de89 jim-p
						break;
337
					case "URI":
338
						/* Close enough? */
339 56b1ed39 Phil Davis
						if (!is_URL($altname['value'])) {
340 2f65de89 jim-p
							$input_errors[] = "URI subjectAltName types must be a valid URI";
341 56b1ed39 Phil Davis
						}
342 2f65de89 jim-p
						break;
343
					default:
344
						$input_errors[] = "Unrecognized subjectAltName type.";
345
				}
346
			}
347
348 21cc2faa Evgeny Yurchenko
			/* Make sure we do not have invalid characters in the fields for the certificate */
349 b741d2ef jim-p
350
			if (preg_match("/[\?\>\<\&\/\\\"\']/", $_POST['descr'])) {
351
				array_push($input_errors, "The field 'Descriptive Name' contains invalid characters.");
352
			}
353
354 21cc2faa Evgeny Yurchenko
			for ($i = 0; $i < count($reqdfields); $i++) {
355 56b1ed39 Phil Davis
				if (preg_match('/email/', $reqdfields[$i])) { /* dn_email or csr_dn_name */
356
					if (preg_match("/[\!\#\$\%\^\(\)\~\?\>\<\&\/\\\,\"\']/", $_POST[$reqdfields[$i]])) {
357 762faef5 Phil Davis
						array_push($input_errors, gettext("The field 'Distinguished name Email Address' contains invalid characters."));
358 56b1ed39 Phil Davis
					}
359
				}
360 21cc2faa Evgeny Yurchenko
			}
361 738fab3d jim-p
362 56b1ed39 Phil Davis
			if (($pconfig['method'] != "external") && isset($_POST["keylen"]) && !in_array($_POST["keylen"], $cert_keylens)) {
363 741d748d jim-p
				array_push($input_errors, gettext("Please select a valid Key Length."));
364 56b1ed39 Phil Davis
			}
365
			if (($pconfig['method'] != "external") && !in_array($_POST["digest_alg"], $openssl_digest_algs)) {
366 8f07b51c PiBa-NL
				array_push($input_errors, gettext("Please select a valid Digest Algorithm."));
367 56b1ed39 Phil Davis
			}
368 b49f31d0 Sjon Hortensius
369 56b1ed39 Phil Davis
			if (($pconfig['method'] == "external") && isset($_POST["csr_keylen"]) && !in_array($_POST["csr_keylen"], $cert_keylens)) {
370 ca621902 jim-p
				array_push($input_errors, gettext("Please select a valid Key Length."));
371 56b1ed39 Phil Davis
			}
372
			if (($pconfig['method'] == "external") && !in_array($_POST["csr_digest_alg"], $openssl_digest_algs)) {
373 ca621902 jim-p
				array_push($input_errors, gettext("Please select a valid Digest Algorithm."));
374 56b1ed39 Phil Davis
			}
375 aec3a259 jim-p
			if (($pconfig['method'] == "sign") && !in_array($_POST["csrsign_digest_alg"], $openssl_digest_algs)) {
376
				array_push($input_errors, gettext("Please select a valid Digest Algorithm."));
377
			}
378 547c56c4 jim-p
		}
379 64cc39d3 Matthew Grooms
380
		/* save modifications */
381
		if (!$input_errors) {
382
383 ad9b5c67 jim-p
			if ($pconfig['method'] == "existing") {
384
				$cert = lookup_cert($pconfig['certref']);
385 56b1ed39 Phil Davis
				if ($cert && $a_user) {
386 ad9b5c67 jim-p
					$a_user[$userid]['cert'][] = $cert['refid'];
387 56b1ed39 Phil Davis
				}
388 2052d3e2 Steve Beaver
			} else if ($pconfig['method'] == "sign") { // Sign a CSR
389 d520da31 Steve Beaver
				$csrid = lookup_cert($pconfig['csrtosign']);
390 2504e3f1 jim-p
				$ca = & lookup_ca($pconfig['catosignwith']);
391 d520da31 Steve Beaver
392
				// Read the CSR from $config, or if a new one, from the textarea
393 2052d3e2 Steve Beaver
				if ($pconfig['csrtosign'] === "new") {
394
					$csr = $pconfig['csrpaste'];
395
				} else {
396 d520da31 Steve Beaver
					$csr = base64_decode($csrid['csr']);
397 2052d3e2 Steve Beaver
				}
398 0c82b8c2 jim-p
				if (count($altnames)) {
399
					foreach ($altnames as $altname) {
400
						$altnames_tmp[] = "{$altname['type']}:" . cert_escape_x509_chars($altname['value']);
401
					}
402
					$altname_str = implode(",", $altnames_tmp);
403 55047259 Steve Beaver
				}
404 2052d3e2 Steve Beaver
405 aec3a259 jim-p
				$n509 = csr_sign($csr, $ca, $pconfig['csrsign_lifetime'], $pconfig['type'], $altname_str, $pconfig['csrsign_digest_alg']);
406 0c82b8c2 jim-p
407
				if ($n509) {
408
					// Gather the details required to save the new cert
409
					$newcert = array();
410
					$newcert['refid'] = uniqid();
411
					$newcert['caref'] = $pconfig['catosignwith'];
412
					$newcert['descr'] = $pconfig['descr'];
413
					$newcert['type'] = $pconfig['type'];
414
					$newcert['crt'] = base64_encode($n509);
415
416
					if ($pconfig['csrtosign'] === "new") {
417
						$newcert['prv'] = base64_encode($pconfig['keypaste']);
418
					} else {
419
						$newcert['prv'] = $csrid['prv'];
420
					}
421 b078cd59 Steve Beaver
422 0c82b8c2 jim-p
					// Add it to the config file
423
					$config['cert'][] = $newcert;
424
				}
425 2052d3e2 Steve Beaver
426 ad9b5c67 jim-p
			} else {
427
				$cert = array();
428
				$cert['refid'] = uniqid();
429 56b1ed39 Phil Davis
				if (isset($id) && $a_cert[$id]) {
430 ad9b5c67 jim-p
					$cert = $a_cert[$id];
431 56b1ed39 Phil Davis
				}
432 ad9b5c67 jim-p
433 f2a86ca9 jim-p
				$cert['descr'] = $pconfig['descr'];
434 ad9b5c67 jim-p
435 f416763b Phil Davis
				$old_err_level = error_reporting(0); /* otherwise openssl_ functions throw warnings directly to a page screwing menu tab */
436 22b380aa Evgeny Yurchenko
437 56b1ed39 Phil Davis
				if ($pconfig['method'] == "import") {
438 ad9b5c67 jim-p
					cert_import($cert, $pconfig['cert'], $pconfig['key']);
439 56b1ed39 Phil Davis
				}
440 ad9b5c67 jim-p
441
				if ($pconfig['method'] == "internal") {
442
					$dn = array(
443
						'countryName' => $pconfig['dn_country'],
444 83d2b83a jim-p
						'stateOrProvinceName' => cert_escape_x509_chars($pconfig['dn_state']),
445
						'localityName' => cert_escape_x509_chars($pconfig['dn_city']),
446
						'organizationName' => cert_escape_x509_chars($pconfig['dn_organization']),
447
						'emailAddress' => cert_escape_x509_chars($pconfig['dn_email']),
448
						'commonName' => cert_escape_x509_chars($pconfig['dn_commonname']));
449 da0f70ed jim-p
					if (!empty($pconfig['dn_organizationalunit'])) {
450 83d2b83a jim-p
						$dn['organizationalUnitName'] = cert_escape_x509_chars($pconfig['dn_organizationalunit']);
451 da0f70ed jim-p
					}
452 e562fca2 jim-p
453
					$altnames_tmp = array();
454
					$cn_altname = cert_add_altname_type($pconfig['dn_commonname']);
455
					if (!empty($cn_altname)) {
456
						$altnames_tmp[] = $cn_altname;
457
					}
458 2f65de89 jim-p
					if (count($altnames)) {
459
						foreach ($altnames as $altname) {
460 a636256c jim-p
							// The CN is added as a SAN automatically, do not add it again.
461
							if ($altname['value'] != $pconfig['dn_commonname']) {
462 2e1809dd jim-p
								$altnames_tmp[] = "{$altname['type']}:" . cert_escape_x509_chars($altname['value']);
463 a636256c jim-p
							}
464 2f65de89 jim-p
						}
465 a636256c jim-p
					}
466
					if (!empty($altnames_tmp)) {
467 2f65de89 jim-p
						$dn['subjectAltName'] = implode(",", $altnames_tmp);
468
					}
469 bf9d50e8 Stephen Beaver
470
					if (!cert_create($cert, $pconfig['caref'], $pconfig['keylen'], $pconfig['lifetime'], $dn, $pconfig['type'], $pconfig['digest_alg'])) {
471 5ce9bcf5 jim-p
						$input_errors = array();
472 56b1ed39 Phil Davis
						while ($ssl_err = openssl_error_string()) {
473 5ce9bcf5 jim-p
							if (strpos($ssl_err, 'NCONF_get_string:no value') === false) {
474
								array_push($input_errors, "openssl library returns: " . $ssl_err);
475
							}
476 22b380aa Evgeny Yurchenko
						}
477
					}
478 ad9b5c67 jim-p
				}
479
480
				if ($pconfig['method'] == "external") {
481
					$dn = array(
482
						'countryName' => $pconfig['csr_dn_country'],
483 83d2b83a jim-p
						'stateOrProvinceName' => cert_escape_x509_chars($pconfig['csr_dn_state']),
484
						'localityName' => cert_escape_x509_chars($pconfig['csr_dn_city']),
485
						'organizationName' => cert_escape_x509_chars($pconfig['csr_dn_organization']),
486
						'emailAddress' => cert_escape_x509_chars($pconfig['csr_dn_email']),
487
						'commonName' => cert_escape_x509_chars($pconfig['csr_dn_commonname']));
488 da0f70ed jim-p
					if (!empty($pconfig['csr_dn_organizationalunit'])) {
489 83d2b83a jim-p
						$dn['organizationalUnitName'] = cert_escape_x509_chars($pconfig['csr_dn_organizationalunit']);
490 da0f70ed jim-p
					}
491 282b6c66 jim-p
492 e562fca2 jim-p
					$altnames_tmp = array();
493
					$cn_altname = cert_add_altname_type($pconfig['csr_dn_commonname']);
494
					if (!empty($cn_altname)) {
495
						$altnames_tmp[] = $cn_altname;
496
					}
497 2f65de89 jim-p
					if (count($altnames)) {
498
						foreach ($altnames as $altname) {
499 282b6c66 jim-p
							// The CN is added as a SAN automatically, do not add it again.
500
							if ($altname['value'] != $pconfig['csr_dn_commonname']) {
501
								$altnames_tmp[] = "{$altname['type']}:" . cert_escape_x509_chars($altname['value']);
502
							}
503 2f65de89 jim-p
						}
504 282b6c66 jim-p
					}
505
					if (!empty($altnames_tmp)) {
506 2f65de89 jim-p
						$dn['subjectAltName'] = implode(",", $altnames_tmp);
507
					}
508 b29c322c Stephen Beaver
509 282b6c66 jim-p
					if (!csr_generate($cert, $pconfig['csr_keylen'], $dn, $pconfig['type'], $pconfig['csr_digest_alg'])) {
510 5ce9bcf5 jim-p
						$input_errors = array();
511 56b1ed39 Phil Davis
						while ($ssl_err = openssl_error_string()) {
512 5ce9bcf5 jim-p
							if (strpos($ssl_err, 'NCONF_get_string:no value') === false) {
513
								array_push($input_errors, "openssl library returns: " . $ssl_err);
514
							}
515 22b380aa Evgeny Yurchenko
						}
516
					}
517 ad9b5c67 jim-p
				}
518 2052d3e2 Steve Beaver
519 22b380aa Evgeny Yurchenko
				error_reporting($old_err_level);
520
521 56b1ed39 Phil Davis
				if (isset($id) && $a_cert[$id]) {
522 ad9b5c67 jim-p
					$a_cert[$id] = $cert;
523 56b1ed39 Phil Davis
				} else {
524 ad9b5c67 jim-p
					$a_cert[] = $cert;
525 56b1ed39 Phil Davis
				}
526 bf9d50e8 Stephen Beaver
527 56b1ed39 Phil Davis
				if (isset($a_user) && isset($userid)) {
528 ad9b5c67 jim-p
					$a_user[$userid]['cert'][] = $cert['refid'];
529 56b1ed39 Phil Davis
				}
530 64cc39d3 Matthew Grooms
			}
531
532 56b1ed39 Phil Davis
			if (!$input_errors) {
533 22b380aa Evgeny Yurchenko
				write_config();
534 56b1ed39 Phil Davis
			}
535 64cc39d3 Matthew Grooms
536 75e80f16 jim-p
			if ($userid && !$input_errors) {
537 1a6769a6 Renato Botelho
				post_redirect("system_usermanager.php", array('act' => 'edit', 'userid' => $userid));
538
				exit;
539
			}
540 64cc39d3 Matthew Grooms
		}
541
	}
542
543 a37753d7 Vinicius Coque
	if ($_POST['save'] == gettext("Update")) {
544 64cc39d3 Matthew Grooms
		unset($input_errors);
545
		$pconfig = $_POST;
546
547
		/* input validation */
548 5293bfec jim-p
		$reqdfields = explode(" ", "descr cert");
549 76d49f20 Renato Botelho
		$reqdfieldsn = array(
550 78863416 Phil Davis
			gettext("Descriptive name"),
551
			gettext("Final Certificate data"));
552 64cc39d3 Matthew Grooms
553 1e9b4611 Renato Botelho
		do_input_validation($_POST, $reqdfields, $reqdfieldsn, $input_errors);
554 64cc39d3 Matthew Grooms
555 b741d2ef jim-p
		if (preg_match("/[\?\>\<\&\/\\\"\']/", $_POST['descr'])) {
556
			array_push($input_errors, "The field 'Descriptive Name' contains invalid characters.");
557
		}
558
559 a828210b yakatz
//		old way
560 64cc39d3 Matthew Grooms
		/* make sure this csr and certificate subjects match */
561 a828210b yakatz
//		$subj_csr = csr_get_subject($pconfig['csr'], false);
562
//		$subj_cert = cert_get_subject($pconfig['cert'], false);
563
//
564 56b1ed39 Phil Davis
//		if (!isset($_POST['ignoresubjectmismatch']) && !($_POST['ignoresubjectmismatch'] == "yes")) {
565
//			if (strcmp($subj_csr, $subj_cert)) {
566
//				$input_errors[] = sprintf(gettext("The certificate subject '%s' does not match the signing request subject."), $subj_cert);
567 a828210b yakatz
//				$subject_mismatch = true;
568
//			}
569
//		}
570 1746c5ce PiBa-NL
		$mod_csr = cert_get_publickey($pconfig['csr'], false, 'csr');
571
		$mod_cert = cert_get_publickey($pconfig['cert'], false);
572 b49f31d0 Sjon Hortensius
573 56b1ed39 Phil Davis
		if (strcmp($mod_csr, $mod_cert)) {
574 a828210b yakatz
			// simply: if the moduli don't match, then the private key and public key won't match
575 1746c5ce PiBa-NL
			$input_errors[] = sprintf(gettext("The certificate public key does not match the signing request public key."), $subj_cert);
576 a828210b yakatz
			$subject_mismatch = true;
577
		}
578 64cc39d3 Matthew Grooms
579
		/* save modifications */
580
		if (!$input_errors) {
581
582
			$cert = $a_cert[$id];
583
584 f2a86ca9 jim-p
			$cert['descr'] = $pconfig['descr'];
585 64cc39d3 Matthew Grooms
586
			csr_complete($cert, $pconfig['cert']);
587
588
			$a_cert[$id] = $cert;
589
590
			write_config();
591
592
			pfSenseHeader("system_certmanager.php");
593
		}
594
	}
595
}
596
597 56c6b1cb k-paulius
$pgtitle = array(gettext("System"), gettext("Certificate Manager"), gettext("Certificates"));
598 edcd7535 Phil Davis
$pglinks = array("", "system_camanager.php", "system_certmanager.php");
599 56c6b1cb k-paulius
600
if (($act == "new" || ($_POST['save'] == gettext("Save") && $input_errors)) || ($act == "csr" || ($_POST['save'] == gettext("Update") && $input_errors))) {
601
	$pgtitle[] = gettext('Edit');
602 edcd7535 Phil Davis
	$pglinks[] = "@self";
603 56c6b1cb k-paulius
}
604 64cc39d3 Matthew Grooms
include("head.inc");
605 b49f31d0 Sjon Hortensius
606 78863416 Phil Davis
if ($input_errors) {
607 b49f31d0 Sjon Hortensius
	print_input_errors($input_errors);
608 78863416 Phil Davis
}
609 0edcccc3 Daniel Seebald
610 78863416 Phil Davis
if ($savemsg) {
611 3f0efd58 Stephen Beaver
	print_info_box($savemsg, 'success');
612 78863416 Phil Davis
}
613 b49f31d0 Sjon Hortensius
614
$tab_array = array();
615
$tab_array[] = array(gettext("CAs"), false, "system_camanager.php");
616
$tab_array[] = array(gettext("Certificates"), true, "system_certmanager.php");
617
$tab_array[] = array(gettext("Certificate Revocation"), false, "system_crlmanager.php");
618
display_top_tabs($tab_array);
619
620
// Load valid country codes
621
$dn_cc = array();
622 78863416 Phil Davis
if (file_exists("/etc/ca_countries")) {
623 b49f31d0 Sjon Hortensius
	$dn_cc_file=file("/etc/ca_countries");
624 78863416 Phil Davis
	foreach ($dn_cc_file as $line) {
625 b8f22f61 Stephen Beaver
		if (preg_match('/^(\S*)\s(.*)$/', $line, $matches)) {
626
			$dn_cc[$matches[1]] = $matches[1];
627
		}
628
	}
629 b49f31d0 Sjon Hortensius
}
630
631 b29c322c Stephen Beaver
if ($act == "new" || (($_POST['save'] == gettext("Save")) && $input_errors)) {
632 b35250d9 NewEraCracker
	$form = new Form();
633
	$form->setAction('system_certmanager.php?act=edit');
634 b49f31d0 Sjon Hortensius
635 b35250d9 NewEraCracker
	if (isset($userid) && $a_user) {
636
		$form->addGlobal(new Form_Input(
637
			'userid',
638
			null,
639
			'hidden',
640
			$userid
641
		));
642
	}
643 b49f31d0 Sjon Hortensius
644 78863416 Phil Davis
	if (isset($id) && $a_cert[$id]) {
645 b49f31d0 Sjon Hortensius
		$form->addGlobal(new Form_Input(
646
			'id',
647
			null,
648
			'hidden',
649
			$id
650
		));
651 64cc39d3 Matthew Grooms
	}
652 b49f31d0 Sjon Hortensius
653 2052d3e2 Steve Beaver
	$section = new Form_Section('Add/Sign a New Certificate');
654 b35250d9 NewEraCracker
655
	if (!isset($id)) {
656
		$section->addInput(new Form_Select(
657
			'method',
658 153c3aa6 Phil Davis
			'*Method',
659 b35250d9 NewEraCracker
			$pconfig['method'],
660
			$cert_methods
661
		))->toggles();
662
	}
663
664 b49f31d0 Sjon Hortensius
	$section->addInput(new Form_Input(
665
		'descr',
666 153c3aa6 Phil Davis
		'*Descriptive name',
667 b49f31d0 Sjon Hortensius
		'text',
668 b35250d9 NewEraCracker
		($a_user && empty($pconfig['descr'])) ? $a_user[$userid]['name'] : $pconfig['descr']
669
	))->addClass('toggle-existing');
670 b49f31d0 Sjon Hortensius
671 b35250d9 NewEraCracker
	$form->add($section);
672 2052d3e2 Steve Beaver
673 d520da31 Steve Beaver
	// Return an array containing the IDs od all CAs
674 2052d3e2 Steve Beaver
	function list_cas() {
675
		global $a_ca;
676
		$allCas = array();
677
678
		foreach ($a_ca as $ca) {
679
			if ($ca['prv']) {
680 d520da31 Steve Beaver
				$allCas[$ca['refid']] = $ca['descr'];
681 2052d3e2 Steve Beaver
			}
682
		}
683
684
		return $allCas;
685
	}
686
687 d520da31 Steve Beaver
	// Return an array containing the IDs od all CSRs
688 2052d3e2 Steve Beaver
	function list_csrs() {
689
		global $config;
690
		$allCsrs = array();
691
692
		foreach ($config['cert'] as $cert) {
693
			if ($cert['csr']) {
694 d520da31 Steve Beaver
				$allCsrs[$cert['refid']] = $cert['descr'];
695 2052d3e2 Steve Beaver
			}
696
		}
697
698 d6107e1a Steve Beaver
		return ['new' => gettext('New CSR (Paste below)')] + $allCsrs;
699 2052d3e2 Steve Beaver
	}
700
701
	$section = new Form_Section('Sign CSR');
702
	$section->addClass('toggle-sign collapse');
703
704
	$section->AddInput(new Form_Select(
705
		'catosignwith',
706
		'*CA to sign with',
707
		$pconfig['catosignwith'],
708
		list_cas()
709
	));
710
711
	$section->AddInput(new Form_Select(
712
		'csrtosign',
713
		'*CSR to sign',
714
		isset($pconfig['csrtosign']) ? $pconfig['csrtosign'] : 'new',
715
		list_csrs()
716
	));
717
718
	$section->addInput(new Form_Textarea(
719
		'csrpaste',
720
		'CSR data',
721
		$pconfig['csrpaste']
722
	))->setHelp('Paste a Certificate Signing Request in X.509 PEM format here.');
723
724 55047259 Steve Beaver
	$section->addInput(new Form_Textarea(
725
		'keypaste',
726
		'Key data',
727
		$pconfig['keypaste']
728
	))->setHelp('Optionally paste a private key here. The key will be associated with the newly signed certificate in pfSense');
729
730 0c82b8c2 jim-p
	$section->addInput(new Form_Input(
731
		'csrsign_lifetime',
732
		'*Certificate Lifetime (days)',
733
		'number',
734 aec3a259 jim-p
		$pconfig['csrsign_lifetime'] ? $pconfig['csrsign_lifetime']:'3650'
735 0c82b8c2 jim-p
	));
736 aec3a259 jim-p
	$section->addInput(new Form_Select(
737
		'csrsign_digest_alg',
738
		'*Digest Algorithm',
739
		$pconfig['csrsign_digest_alg'],
740
		array_combine($openssl_digest_algs, $openssl_digest_algs)
741
	))->setHelp('NOTE: It is recommended to use an algorithm stronger than '.
742
		'SHA1 when possible');
743 0c82b8c2 jim-p
744 2052d3e2 Steve Beaver
	$form->add($section);
745
746 b35250d9 NewEraCracker
	$section = new Form_Section('Import Certificate');
747
	$section->addClass('toggle-import collapse');
748 b49f31d0 Sjon Hortensius
749
	$section->addInput(new Form_Textarea(
750
		'cert',
751 153c3aa6 Phil Davis
		'*Certificate data',
752 78863416 Phil Davis
		$pconfig['cert']
753 b35250d9 NewEraCracker
	))->setHelp('Paste a certificate in X.509 PEM format here.');
754
755
	$section->addInput(new Form_Textarea(
756
		'key',
757 153c3aa6 Phil Davis
		'*Private key data',
758 b35250d9 NewEraCracker
		$pconfig['key']
759
	))->setHelp('Paste a private key in X.509 PEM format here.');
760 b49f31d0 Sjon Hortensius
761
	$form->add($section);
762 b35250d9 NewEraCracker
	$section = new Form_Section('Internal Certificate');
763
	$section->addClass('toggle-internal collapse');
764
765
	if (!$internal_ca_count) {
766
		$section->addInput(new Form_StaticText(
767 153c3aa6 Phil Davis
			'*Certificate authority',
768 781d9ce4 Phil Davis
			gettext('No internal Certificate Authorities have been defined. ') .
769
			gettext('An internal CA must be defined in order to create an internal certificate. ') .
770
			sprintf(gettext('%1$sCreate%2$s an internal CA.'), '<a href="system_camanager.php?act=new&amp;method=internal"> ', '</a>')
771 b35250d9 NewEraCracker
		));
772
	} else {
773
		$allCas = array();
774
		foreach ($a_ca as $ca) {
775
			if (!$ca['prv']) {
776
				continue;
777
			}
778 b49f31d0 Sjon Hortensius
779 b35250d9 NewEraCracker
			$allCas[ $ca['refid'] ] = $ca['descr'];
780
		}
781 64cc39d3 Matthew Grooms
782 b35250d9 NewEraCracker
		$section->addInput(new Form_Select(
783
			'caref',
784 153c3aa6 Phil Davis
			'*Certificate authority',
785 b35250d9 NewEraCracker
			$pconfig['caref'],
786
			$allCas
787
		));
788
	}
789 64cc39d3 Matthew Grooms
790 b35250d9 NewEraCracker
	$section->addInput(new Form_Select(
791
		'keylen',
792 153c3aa6 Phil Davis
		'*Key length',
793 b35250d9 NewEraCracker
		$pconfig['keylen'],
794
		array_combine($cert_keylens, $cert_keylens)
795 b49f31d0 Sjon Hortensius
	));
796 64cc39d3 Matthew Grooms
797 b35250d9 NewEraCracker
	$section->addInput(new Form_Select(
798
		'digest_alg',
799 153c3aa6 Phil Davis
		'*Digest Algorithm',
800 b35250d9 NewEraCracker
		$pconfig['digest_alg'],
801
		array_combine($openssl_digest_algs, $openssl_digest_algs)
802
	))->setHelp('NOTE: It is recommended to use an algorithm stronger than '.
803
		'SHA1 when possible.');
804 b49f31d0 Sjon Hortensius
805 b35250d9 NewEraCracker
	$section->addInput(new Form_Input(
806
		'lifetime',
807 153c3aa6 Phil Davis
		'*Lifetime (days)',
808 b35250d9 NewEraCracker
		'number',
809
		$pconfig['lifetime']
810
	));
811 b49f31d0 Sjon Hortensius
812
	$section->addInput(new Form_Select(
813 b35250d9 NewEraCracker
		'dn_country',
814 153c3aa6 Phil Davis
		'*Country Code',
815 b35250d9 NewEraCracker
		$pconfig['dn_country'],
816
		$dn_cc
817 b49f31d0 Sjon Hortensius
	));
818
819 b35250d9 NewEraCracker
	$section->addInput(new Form_Input(
820
		'dn_state',
821 153c3aa6 Phil Davis
		'*State or Province',
822 b35250d9 NewEraCracker
		'text',
823
		$pconfig['dn_state'],
824
		['placeholder' => 'e.g. Texas']
825 b49f31d0 Sjon Hortensius
	));
826
827 b35250d9 NewEraCracker
	$section->addInput(new Form_Input(
828
		'dn_city',
829 153c3aa6 Phil Davis
		'*City',
830 b35250d9 NewEraCracker
		'text',
831
		$pconfig['dn_city'],
832
		['placeholder' => 'e.g. Austin']
833
	));
834
835
	$section->addInput(new Form_Input(
836
		'dn_organization',
837 153c3aa6 Phil Davis
		'*Organization',
838 b35250d9 NewEraCracker
		'text',
839
		$pconfig['dn_organization'],
840 da0f70ed jim-p
		['placeholder' => 'e.g. My Company Inc']
841
	));
842
843
	$section->addInput(new Form_Input(
844
		'dn_organizationalunit',
845
		'Organizational Unit',
846
		'text',
847
		$pconfig['dn_organizationalunit'],
848
		['placeholder' => 'e.g. My Department Name (optional)']
849 b35250d9 NewEraCracker
	));
850
851
	$section->addInput(new Form_Input(
852
		'dn_email',
853 153c3aa6 Phil Davis
		'*Email Address',
854 b35250d9 NewEraCracker
		'text',
855
		$pconfig['dn_email'],
856
		['placeholder' => 'e.g. admin@mycompany.com']
857
	));
858
859
	$section->addInput(new Form_Input(
860
		'dn_commonname',
861 153c3aa6 Phil Davis
		'*Common Name',
862 b35250d9 NewEraCracker
		'text',
863
		$pconfig['dn_commonname'],
864
		['placeholder' => 'e.g. www.example.com']
865
	));
866
867
	$form->add($section);
868
	$section = new Form_Section('External Signing Request');
869
	$section->addClass('toggle-external collapse');
870
871 b49f31d0 Sjon Hortensius
	$section->addInput(new Form_Select(
872 b35250d9 NewEraCracker
		'csr_keylen',
873 153c3aa6 Phil Davis
		'*Key length',
874 b35250d9 NewEraCracker
		$pconfig['csr_keylen'],
875
		array_combine($cert_keylens, $cert_keylens)
876 b49f31d0 Sjon Hortensius
	));
877 64cc39d3 Matthew Grooms
878 b35250d9 NewEraCracker
	$section->addInput(new Form_Select(
879
		'csr_digest_alg',
880 153c3aa6 Phil Davis
		'*Digest Algorithm',
881 b35250d9 NewEraCracker
		$pconfig['csr_digest_alg'],
882
		array_combine($openssl_digest_algs, $openssl_digest_algs)
883
	))->setHelp('NOTE: It is recommended to use an algorithm stronger than '.
884
		'SHA1 when possible');
885 b49f31d0 Sjon Hortensius
886 b35250d9 NewEraCracker
	$section->addInput(new Form_Select(
887
		'csr_dn_country',
888 153c3aa6 Phil Davis
		'*Country Code',
889 b35250d9 NewEraCracker
		$pconfig['csr_dn_country'],
890
		$dn_cc
891
	));
892 bf9d50e8 Stephen Beaver
893 b35250d9 NewEraCracker
	$section->addInput(new Form_Input(
894
		'csr_dn_state',
895 153c3aa6 Phil Davis
		'*State or Province',
896 b35250d9 NewEraCracker
		'text',
897
		$pconfig['csr_dn_state'],
898
		['placeholder' => 'e.g. Texas']
899
	));
900 bf9d50e8 Stephen Beaver
901 b35250d9 NewEraCracker
	$section->addInput(new Form_Input(
902
		'csr_dn_city',
903 153c3aa6 Phil Davis
		'*City',
904 b35250d9 NewEraCracker
		'text',
905
		$pconfig['csr_dn_city'],
906
		['placeholder' => 'e.g. Austin']
907
	));
908 bf9d50e8 Stephen Beaver
909 b35250d9 NewEraCracker
	$section->addInput(new Form_Input(
910
		'csr_dn_organization',
911 153c3aa6 Phil Davis
		'*Organization',
912 b35250d9 NewEraCracker
		'text',
913
		$pconfig['csr_dn_organization'],
914 da0f70ed jim-p
		['placeholder' => 'e.g. My Company Inc']
915
	));
916
917
	$section->addInput(new Form_Input(
918
		'csr_dn_organizationalunit',
919
		'Organizational Unit',
920
		'text',
921
		$pconfig['csr_dn_organizationalunit'],
922
		['placeholder' => 'e.g. My Department Name (optional)']
923 b35250d9 NewEraCracker
	));
924 b49f31d0 Sjon Hortensius
925 b35250d9 NewEraCracker
	$section->addInput(new Form_Input(
926
		'csr_dn_email',
927 153c3aa6 Phil Davis
		'*Email Address',
928 b49f31d0 Sjon Hortensius
		'text',
929 b35250d9 NewEraCracker
		$pconfig['csr_dn_email'],
930
		['placeholder' => 'e.g. admin@mycompany.com']
931
	));
932 bf9d50e8 Stephen Beaver
933 b35250d9 NewEraCracker
	$section->addInput(new Form_Input(
934
		'csr_dn_commonname',
935 153c3aa6 Phil Davis
		'*Common Name',
936 b35250d9 NewEraCracker
		'text',
937
		$pconfig['csr_dn_commonname'],
938
		['placeholder' => 'e.g. internal-ca']
939
	));
940 bf9d50e8 Stephen Beaver
941 0c82b8c2 jim-p
	$form->add($section);
942
	$section = new Form_Section('Choose an Existing Certificate');
943
	$section->addClass('toggle-existing collapse');
944
945
	$existCerts = array();
946
947
	foreach ($config['cert'] as $cert)	{
948
		if (is_array($config['system']['user'][$userid]['cert'])) { // Could be MIA!
949
			if (isset($userid) && in_array($cert['refid'], $config['system']['user'][$userid]['cert'])) {
950
				continue;
951
			}
952
		}
953
954
		$ca = lookup_ca($cert['caref']);
955
		if ($ca) {
956
			$cert['descr'] .= " (CA: {$ca['descr']})";
957
		}
958
959
		if (cert_in_use($cert['refid'])) {
960
			$cert['descr'] .= " (In Use)";
961
		}
962
		if (is_cert_revoked($cert)) {
963
			$cert['descr'] .= " (Revoked)";
964
		}
965
966
		$existCerts[ $cert['refid'] ] = $cert['descr'];
967
	}
968
969
	$section->addInput(new Form_Select(
970
		'certref',
971
		'*Existing Certificates',
972
		$pconfig['certref'],
973
		$existCerts
974
	));
975
976
	$form->add($section);
977
978
	$section = new Form_Section('Certificate Attributes');
979
	$section->addClass('toggle-external toggle-internal toggle-sign collapse');
980
981
	$section->addInput(new Form_StaticText(
982
		gettext('Attribute Notes'),
983
		'<span class="help-block">'.
984
		gettext('The following attributes are added to certificates and ' .
985
		'requests when they are created or signed. These attributes behave ' .
986
		'differently depending on the selected mode.') .
987
		'<br/><br/>' .
988
		'<span class="toggle-internal collapse">' . gettext('For Internal Certificates, these attributes are added directly to the certificate as shown.') . '</span>' .
989
		'<span class="toggle-external collapse">' .
990
		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. ') .
991
		'<br/><br/>' .
992
		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>' .
993
		'<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>' .
994
		'</span>'
995
	));
996
997
	$section->addInput(new Form_Select(
998
		'type',
999
		'*Certificate Type',
1000
		$pconfig['type'],
1001
		$cert_types
1002
	))->setHelp('Add type-specific usage attributes to the signed certificate.' .
1003
		' Used for placing usage restrictions on, or granting abilities to, ' .
1004
		'the signed certificate.');
1005
1006 282b6c66 jim-p
	if (empty($pconfig['altnames']['item'])) {
1007
		$pconfig['altnames']['item'] = array(
1008
			array('type' => null, 'value' => null)
1009
		);
1010
	}
1011
1012
	$counter = 0;
1013
	$numrows = count($pconfig['altnames']['item']) - 1;
1014
1015
	foreach ($pconfig['altnames']['item'] as $item) {
1016
1017
		$group = new Form_Group($counter == 0 ? 'Alternative Names':'');
1018
1019
		$group->add(new Form_Select(
1020
			'altname_type' . $counter,
1021
			'Type',
1022
			$item['type'],
1023
			$cert_altname_types
1024
		))->setHelp(($counter == $numrows) ? 'Type':null);
1025
1026
		$group->add(new Form_Input(
1027
			'altname_value' . $counter,
1028
			null,
1029
			'text',
1030
			$item['value']
1031
		))->setHelp(($counter == $numrows) ? 'Value':null);
1032
1033
		$group->add(new Form_Button(
1034
			'deleterow' . $counter,
1035
			'Delete',
1036
			null,
1037
			'fa-trash'
1038
		))->addClass('btn-warning');
1039
1040
		$group->addClass('repeatable');
1041
1042 0c82b8c2 jim-p
		$group->setHelp('Enter additional identifiers for the certificate ' .
1043
			'in this list. The Common Name field is automatically ' .
1044
			'added to the certificate as an Alternative Name. ' .
1045
			'The signing CA may ignore or change these values.');
1046 282b6c66 jim-p
1047
		$section->add($group);
1048
1049
		$counter++;
1050
	}
1051
1052
	$section->addInput(new Form_Button(
1053
		'addrow',
1054
		'Add',
1055
		null,
1056
		'fa-plus'
1057
	))->addClass('btn-success');
1058
1059 b35250d9 NewEraCracker
	$form->add($section);
1060 b49f31d0 Sjon Hortensius
1061
1062 b35250d9 NewEraCracker
	print $form;
1063 64cc39d3 Matthew Grooms
1064 b29c322c Stephen Beaver
} else if ($act == "csr" || (($_POST['save'] == gettext("Update")) && $input_errors)) {
1065 8f58b51b jim-p
	$form = new Form(false);
1066 308f0665 NewEraCracker
	$form->setAction('system_certmanager.php?act=csr');
1067 b29c322c Stephen Beaver
1068 5f88f964 k-paulius
	$section = new Form_Section("Complete Signing Request for " . $pconfig['descr']);
1069 b29c322c Stephen Beaver
1070 ba5c55e9 Stephen Beaver
	$section->addInput(new Form_Input(
1071
		'descr',
1072 153c3aa6 Phil Davis
		'*Descriptive name',
1073 ba5c55e9 Stephen Beaver
		'text',
1074
		$pconfig['descr']
1075
	));
1076
1077 b29c322c Stephen Beaver
	$section->addInput(new Form_Textarea(
1078
		'csr',
1079
		'Signing request data',
1080
		$pconfig['csr']
1081
	))->setReadonly()
1082 af28e231 Stephen Beaver
	  ->setWidth(7)
1083 813c6673 NOYB
	  ->setHelp('Copy the certificate signing data from here and forward it to a certificate authority for signing.');
1084 b29c322c Stephen Beaver
1085
	$section->addInput(new Form_Textarea(
1086
		'cert',
1087 153c3aa6 Phil Davis
		'*Final certificate data',
1088 b29c322c Stephen Beaver
		$pconfig['cert']
1089 af28e231 Stephen Beaver
	))->setWidth(7)
1090 813c6673 NOYB
	  ->setHelp('Paste the certificate received from the certificate authority here.');
1091 b29c322c Stephen Beaver
1092
	 if (isset($id) && $a_cert[$id]) {
1093
		 $section->addInput(new Form_Input(
1094
			'id',
1095
			null,
1096
			'hidden',
1097
			$id
1098
		 ));
1099
1100
		 $section->addInput(new Form_Input(
1101
			'act',
1102
			null,
1103
			'hidden',
1104
			'csr'
1105
		 ));
1106
	 }
1107
1108
	$form->add($section);
1109 8f58b51b jim-p
1110
	$form->addGlobal(new Form_Button(
1111 141d8913 jim-p
		'save',
1112 faab522f Renato Botelho
		'Update',
1113 8f58b51b jim-p
		null,
1114
		'fa-save'
1115
	))->addClass('btn-primary');
1116
1117 b29c322c Stephen Beaver
	print($form);
1118
} else {
1119
?>
1120 060ed238 Stephen Beaver
<div class="panel panel-default">
1121
	<div class="panel-heading"><h2 class="panel-title"><?=gettext('Certificates')?></h2></div>
1122
	<div class="panel-body">
1123
		<div class="table-responsive">
1124
		<table class="table table-striped table-hover">
1125
			<thead>
1126
				<tr>
1127
					<th><?=gettext("Name")?></th>
1128
					<th><?=gettext("Issuer")?></th>
1129
					<th><?=gettext("Distinguished Name")?></th>
1130
					<th><?=gettext("In Use")?></th>
1131 4db1f211 Stephen Beaver
1132 060ed238 Stephen Beaver
					<th class="col-sm-2"><?=gettext("Actions")?></th>
1133
				</tr>
1134
			</thead>
1135
			<tbody>
1136 b29c322c Stephen Beaver
<?php
1137 4db1f211 Stephen Beaver
1138
$pluginparams = array();
1139
$pluginparams['type'] = 'certificates';
1140
$pluginparams['event'] = 'used_certificates';
1141
$certificates_used_by_packages = pkg_call_plugins('plugin_certificates', $pluginparams);
1142
$i = 0;
1143 78863416 Phil Davis
foreach ($a_cert as $i => $cert):
1144 b29c322c Stephen Beaver
	$name = htmlspecialchars($cert['descr']);
1145 00d5594c jim-p
	$sans = array();
1146 b29c322c Stephen Beaver
	if ($cert['crt']) {
1147
		$subj = cert_get_subject($cert['crt']);
1148
		$issuer = cert_get_issuer($cert['crt']);
1149
		$purpose = cert_get_purpose($cert['crt']);
1150 4906f4ee jim-p
		$sans = cert_get_sans($cert['crt']);
1151 b29c322c Stephen Beaver
		list($startdate, $enddate) = cert_get_dates($cert['crt']);
1152
1153 78863416 Phil Davis
		if ($subj == $issuer) {
1154 b29c322c Stephen Beaver
			$caname = '<i>'. gettext("self-signed") .'</i>';
1155 78863416 Phil Davis
		} else {
1156 b29c322c Stephen Beaver
			$caname = '<i>'. gettext("external").'</i>';
1157 78863416 Phil Davis
		}
1158 b29c322c Stephen Beaver
1159 83d2b83a jim-p
		$subj = htmlspecialchars(cert_escape_x509_chars($subj, true));
1160 1048585a PiBa-NL
	} else {
1161
		$subj = "";
1162
		$issuer = "";
1163
		$purpose = "";
1164
		$startdate = "";
1165
		$enddate = "";
1166
		$caname = "<em>" . gettext("private key only") . "</em>";
1167 b29c322c Stephen Beaver
	}
1168
1169
	if ($cert['csr']) {
1170 83d2b83a jim-p
		$subj = htmlspecialchars(cert_escape_x509_chars(csr_get_subject($cert['csr']), true));
1171 4906f4ee jim-p
		$sans = cert_get_sans($cert['crt']);
1172 b29c322c Stephen Beaver
		$caname = "<em>" . gettext("external - signature pending") . "</em>";
1173
	}
1174
1175
	$ca = lookup_ca($cert['caref']);
1176 78863416 Phil Davis
	if ($ca) {
1177 b29c322c Stephen Beaver
		$caname = $ca['descr'];
1178 78863416 Phil Davis
	}
1179 b29c322c Stephen Beaver
?>
1180 060ed238 Stephen Beaver
				<tr>
1181
					<td>
1182
						<?=$name?><br />
1183
						<?php if ($cert['type']): ?>
1184
							<i><?=$cert_types[$cert['type']]?></i><br />
1185
						<?php endif?>
1186
						<?php if (is_array($purpose)): ?>
1187 4906f4ee jim-p
							CA: <b><?=$purpose['ca']?></b><br/>
1188
							<?=gettext("Server")?>: <b><?=$purpose['server']?></b><br/>
1189 060ed238 Stephen Beaver
						<?php endif?>
1190
					</td>
1191
					<td><?=$caname?></td>
1192
					<td>
1193
						<?=$subj?>
1194 4906f4ee jim-p
						<?php
1195
						$certextinfo = "";
1196 aec3a259 jim-p
						$certserial = cert_get_serial($cert['crt']);
1197
						if (!empty($certserial)) {
1198
							$certextinfo .= '<b>' . gettext("Serial: ") . '</b> ';
1199
							$certextinfo .= htmlspecialchars(cert_escape_x509_chars($certserial, true));
1200
							$certextinfo .= '<br/>';
1201
						}
1202
						$certsig = cert_get_sigtype($cert['crt']);
1203
						if (is_array($certsig) && !empty($certsig) && !empty($certsig['shortname'])) {
1204
							$certextinfo .= '<b>' . gettext("Signature Digest: ") . '</b> ';
1205
							$certextinfo .= htmlspecialchars(cert_escape_x509_chars($certsig['shortname'], true));
1206
							$certextinfo .= '<br/>';
1207
						}
1208 4906f4ee jim-p
						if (is_array($sans) && !empty($sans)) {
1209
							$certextinfo .= '<b>' . gettext("SAN: ") . '</b> ';
1210 2e1809dd jim-p
							$certextinfo .= htmlspecialchars(implode(', ', cert_escape_x509_chars($sans, true)));
1211 4906f4ee jim-p
							$certextinfo .= '<br/>';
1212
						}
1213
						if (is_array($purpose) && !empty($purpose['ku'])) {
1214
							$certextinfo .= '<b>' . gettext("KU: ") . '</b> ';
1215
							$certextinfo .= htmlspecialchars(implode(', ', $purpose['ku']));
1216
							$certextinfo .= '<br/>';
1217
						}
1218
						if (is_array($purpose) && !empty($purpose['eku'])) {
1219
							$certextinfo .= '<b>' . gettext("EKU: ") . '</b> ';
1220
							$certextinfo .= htmlspecialchars(implode(', ', $purpose['eku']));
1221
						}
1222
						?>
1223
						<?php if (!empty($certextinfo)): ?>
1224
							<div class="infoblock">
1225
							<? print_info_box($certextinfo, 'info', false); ?>
1226
							</div>
1227
						<?php endif?>
1228
1229
						<?php if (!empty($startdate) || !empty($enddate)): ?>
1230 b090c741 jim-p
						<br />
1231 060ed238 Stephen Beaver
						<small>
1232
							<?=gettext("Valid From")?>: <b><?=$startdate ?></b><br /><?=gettext("Valid Until")?>: <b><?=$enddate ?></b>
1233
						</small>
1234
						<?php endif?>
1235
					</td>
1236
					<td>
1237
						<?php if (is_cert_revoked($cert)): ?>
1238 762faef5 Phil Davis
							<i><?=gettext("Revoked")?></i>
1239 060ed238 Stephen Beaver
						<?php endif?>
1240
						<?php if (is_webgui_cert($cert['refid'])): ?>
1241 762faef5 Phil Davis
							<?=gettext("webConfigurator")?>
1242 060ed238 Stephen Beaver
						<?php endif?>
1243
						<?php if (is_user_cert($cert['refid'])): ?>
1244 762faef5 Phil Davis
							<?=gettext("User Cert")?>
1245 060ed238 Stephen Beaver
						<?php endif?>
1246
						<?php if (is_openvpn_server_cert($cert['refid'])): ?>
1247 762faef5 Phil Davis
							<?=gettext("OpenVPN Server")?>
1248 060ed238 Stephen Beaver
						<?php endif?>
1249
						<?php if (is_openvpn_client_cert($cert['refid'])): ?>
1250 762faef5 Phil Davis
							<?=gettext("OpenVPN Client")?>
1251 060ed238 Stephen Beaver
						<?php endif?>
1252
						<?php if (is_ipsec_cert($cert['refid'])): ?>
1253 762faef5 Phil Davis
							<?=gettext("IPsec Tunnel")?>
1254 060ed238 Stephen Beaver
						<?php endif?>
1255
						<?php if (is_captiveportal_cert($cert['refid'])): ?>
1256 762faef5 Phil Davis
							<?=gettext("Captive Portal")?>
1257 060ed238 Stephen Beaver
						<?php endif?>
1258 3bde5cdd PiBa-NL
						<?php echo cert_usedby_description($cert['refid'], $certificates_used_by_packages); ?>
1259 060ed238 Stephen Beaver
					</td>
1260
					<td>
1261
						<?php if (!$cert['csr']): ?>
1262 4611e283 Steve Beaver
							<a href="system_certmanager.php?act=exp&amp;id=<?=$i?>" class="fa fa-certificate" title="<?=gettext("Export Certificate")?>"></a>
1263 4594038a Steve Beaver
							<?php if ($cert['prv']): ?>
1264
								<a href="system_certmanager.php?act=key&amp;id=<?=$i?>" class="fa fa-key" title="<?=gettext("Export Key")?>"></a>
1265
							<?php endif?>
1266 4611e283 Steve Beaver
							<a href="system_certmanager.php?act=p12&amp;id=<?=$i?>" class="fa fa-archive" title="<?=gettext("Export P12")?>"></a>
1267 060ed238 Stephen Beaver
						<?php else: ?>
1268 4611e283 Steve Beaver
							<a href="system_certmanager.php?act=csr&amp;id=<?=$i?>" class="fa fa-pencil" title="<?=gettext("Update CSR")?>"></a>
1269
							<a href="system_certmanager.php?act=req&amp;id=<?=$i?>" class="fa fa-sign-in" title="<?=gettext("Export Request")?>"></a>
1270
							<a href="system_certmanager.php?act=key&amp;id=<?=$i?>" class="fa fa-key" title="<?=gettext("Export Key")?>"></a>
1271 060ed238 Stephen Beaver
						<?php endif?>
1272
						<?php if (!cert_in_use($cert['refid'])): ?>
1273 fe914124 Steve Beaver
							<a href="system_certmanager.php?act=del&amp;id=<?=$i?>" class="fa fa-trash" title="<?=gettext("Delete Certificate")?>" usepost></a>
1274 060ed238 Stephen Beaver
						<?php endif?>
1275
					</td>
1276
				</tr>
1277 4db1f211 Stephen Beaver
<?php
1278 e8afd822 Steve Beaver
	$i++;
1279 4db1f211 Stephen Beaver
	endforeach; ?>
1280 060ed238 Stephen Beaver
			</tbody>
1281
		</table>
1282
		</div>
1283
	</div>
1284 b29c322c Stephen Beaver
</div>
1285
1286
<nav class="action-buttons">
1287 4611e283 Steve Beaver
	<a href="?act=new" class="btn btn-success btn-sm">
1288 b29c322c Stephen Beaver
		<i class="fa fa-plus icon-embed-btn"></i>
1289 2052d3e2 Steve Beaver
		<?=gettext("Add/Sign")?>
1290 b29c322c Stephen Beaver
	</a>
1291
</nav>
1292 e9258698 NewEraCracker
<?php
1293 b29c322c Stephen Beaver
	include("foot.inc");
1294
	exit;
1295
}
1296
1297
1298 51583438 Stephen Beaver
?>
1299 8fd9052f Colin Fleming
<script type="text/javascript">
1300 51583438 Stephen Beaver
//<![CDATA[
1301 78863416 Phil Davis
events.push(function() {
1302 bf9d50e8 Stephen Beaver
1303 51583438 Stephen Beaver
<?php if ($internal_ca_count): ?>
1304
	function internalca_change() {
1305
1306
		caref = $('#caref').val();
1307
1308
		switch (caref) {
1309
<?php
1310
			foreach ($a_ca as $ca):
1311
				if (!$ca['prv']) {
1312
					continue;
1313
				}
1314
1315
				$subject = cert_get_subject_array($ca['crt']);
1316
?>
1317
				case "<?=$ca['refid'];?>":
1318 83d2b83a jim-p
					$('#dn_country').val(<?=json_encode(cert_escape_x509_chars($subject[0]['v'], true));?>);
1319
					$('#dn_state').val(<?=json_encode(cert_escape_x509_chars($subject[1]['v'], true));?>);
1320
					$('#dn_city').val(<?=json_encode(cert_escape_x509_chars($subject[2]['v'], true));?>);
1321
					$('#dn_organization').val(<?=json_encode(cert_escape_x509_chars($subject[3]['v'], true));?>);
1322
					$('#dn_email').val(<?=json_encode(cert_escape_x509_chars($subject[4]['v'], true));?>);
1323
					$('#dn_organizationalunit').val(<?=json_encode(cert_escape_x509_chars($subject[6]['v'], true));?>);
1324 51583438 Stephen Beaver
					break;
1325
<?php
1326
			endforeach;
1327
?>
1328
		}
1329
	}
1330
1331 2052d3e2 Steve Beaver
	function set_csr_ro() {
1332 b078cd59 Steve Beaver
		var newcsr = ($('#csrtosign').val() == "new");
1333 65d735f0 Steve Beaver
1334
		$('#csrpaste').attr('readonly', !newcsr);
1335 55047259 Steve Beaver
		$('#keypaste').attr('readonly', !newcsr);
1336 65d735f0 Steve Beaver
		setRequired('csrpaste', newcsr);
1337 2052d3e2 Steve Beaver
	}
1338
1339 eef93144 Jared Dillard
	// ---------- Click checkbox handlers ---------------------------------------------------------
1340 f74457df Stephen Beaver
1341 51583438 Stephen Beaver
	$('#caref').on('change', function() {
1342
		internalca_change();
1343
	});
1344
1345 2052d3e2 Steve Beaver
	$('#csrtosign').change(function () {
1346
		set_csr_ro();
1347
	});
1348
1349 eef93144 Jared Dillard
	// ---------- On initial page load ------------------------------------------------------------
1350
1351 51583438 Stephen Beaver
	internalca_change();
1352 2052d3e2 Steve Beaver
	set_csr_ro();
1353 51583438 Stephen Beaver
1354 0bc61baa Stephen Beaver
	// Suppress "Delete row" button if there are fewer than two rows
1355
	checkLastRow();
1356
1357 51583438 Stephen Beaver
<?php endif; ?>
1358
1359
1360
});
1361
//]]>
1362
</script>
1363
<?php
1364 0edcccc3 Daniel Seebald
include('foot.inc');