Project

General

Profile

Download (39.1 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 81299b5c Renato Botelho
 * Copyright (c) 2004-2016 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 0edcccc3 Daniel Seebald
						if (!is_hostname($altname['value'], true)) {
321
							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 2e1809dd jim-p
					$altnames_tmp = array(cert_add_altname_type($pconfig['dn_commonname']));
453 2f65de89 jim-p
					if (count($altnames)) {
454
						foreach ($altnames as $altname) {
455 a636256c jim-p
							// The CN is added as a SAN automatically, do not add it again.
456
							if ($altname['value'] != $pconfig['dn_commonname']) {
457 2e1809dd jim-p
								$altnames_tmp[] = "{$altname['type']}:" . cert_escape_x509_chars($altname['value']);
458 a636256c jim-p
							}
459 2f65de89 jim-p
						}
460 a636256c jim-p
					}
461
					if (!empty($altnames_tmp)) {
462 2f65de89 jim-p
						$dn['subjectAltName'] = implode(",", $altnames_tmp);
463
					}
464 bf9d50e8 Stephen Beaver
465
					if (!cert_create($cert, $pconfig['caref'], $pconfig['keylen'], $pconfig['lifetime'], $dn, $pconfig['type'], $pconfig['digest_alg'])) {
466 5ce9bcf5 jim-p
						$input_errors = array();
467 56b1ed39 Phil Davis
						while ($ssl_err = openssl_error_string()) {
468 5ce9bcf5 jim-p
							if (strpos($ssl_err, 'NCONF_get_string:no value') === false) {
469
								array_push($input_errors, "openssl library returns: " . $ssl_err);
470
							}
471 22b380aa Evgeny Yurchenko
						}
472
					}
473 ad9b5c67 jim-p
				}
474
475
				if ($pconfig['method'] == "external") {
476
					$dn = array(
477
						'countryName' => $pconfig['csr_dn_country'],
478 83d2b83a jim-p
						'stateOrProvinceName' => cert_escape_x509_chars($pconfig['csr_dn_state']),
479
						'localityName' => cert_escape_x509_chars($pconfig['csr_dn_city']),
480
						'organizationName' => cert_escape_x509_chars($pconfig['csr_dn_organization']),
481
						'emailAddress' => cert_escape_x509_chars($pconfig['csr_dn_email']),
482
						'commonName' => cert_escape_x509_chars($pconfig['csr_dn_commonname']));
483 da0f70ed jim-p
					if (!empty($pconfig['csr_dn_organizationalunit'])) {
484 83d2b83a jim-p
						$dn['organizationalUnitName'] = cert_escape_x509_chars($pconfig['csr_dn_organizationalunit']);
485 da0f70ed jim-p
					}
486 282b6c66 jim-p
487
					$altnames_tmp = array(cert_add_altname_type($pconfig['csr_dn_commonname']));
488 2f65de89 jim-p
					if (count($altnames)) {
489
						foreach ($altnames as $altname) {
490 282b6c66 jim-p
							// The CN is added as a SAN automatically, do not add it again.
491
							if ($altname['value'] != $pconfig['csr_dn_commonname']) {
492
								$altnames_tmp[] = "{$altname['type']}:" . cert_escape_x509_chars($altname['value']);
493
							}
494 2f65de89 jim-p
						}
495 282b6c66 jim-p
					}
496
					if (!empty($altnames_tmp)) {
497 2f65de89 jim-p
						$dn['subjectAltName'] = implode(",", $altnames_tmp);
498
					}
499 b29c322c Stephen Beaver
500 282b6c66 jim-p
					if (!csr_generate($cert, $pconfig['csr_keylen'], $dn, $pconfig['type'], $pconfig['csr_digest_alg'])) {
501 5ce9bcf5 jim-p
						$input_errors = array();
502 56b1ed39 Phil Davis
						while ($ssl_err = openssl_error_string()) {
503 5ce9bcf5 jim-p
							if (strpos($ssl_err, 'NCONF_get_string:no value') === false) {
504
								array_push($input_errors, "openssl library returns: " . $ssl_err);
505
							}
506 22b380aa Evgeny Yurchenko
						}
507
					}
508 ad9b5c67 jim-p
				}
509 2052d3e2 Steve Beaver
510 22b380aa Evgeny Yurchenko
				error_reporting($old_err_level);
511
512 56b1ed39 Phil Davis
				if (isset($id) && $a_cert[$id]) {
513 ad9b5c67 jim-p
					$a_cert[$id] = $cert;
514 56b1ed39 Phil Davis
				} else {
515 ad9b5c67 jim-p
					$a_cert[] = $cert;
516 56b1ed39 Phil Davis
				}
517 bf9d50e8 Stephen Beaver
518 56b1ed39 Phil Davis
				if (isset($a_user) && isset($userid)) {
519 ad9b5c67 jim-p
					$a_user[$userid]['cert'][] = $cert['refid'];
520 56b1ed39 Phil Davis
				}
521 64cc39d3 Matthew Grooms
			}
522
523 56b1ed39 Phil Davis
			if (!$input_errors) {
524 22b380aa Evgeny Yurchenko
				write_config();
525 56b1ed39 Phil Davis
			}
526 64cc39d3 Matthew Grooms
527 75e80f16 jim-p
			if ($userid && !$input_errors) {
528 1a6769a6 Renato Botelho
				post_redirect("system_usermanager.php", array('act' => 'edit', 'userid' => $userid));
529
				exit;
530
			}
531 64cc39d3 Matthew Grooms
		}
532
	}
533
534 a37753d7 Vinicius Coque
	if ($_POST['save'] == gettext("Update")) {
535 64cc39d3 Matthew Grooms
		unset($input_errors);
536
		$pconfig = $_POST;
537
538
		/* input validation */
539 5293bfec jim-p
		$reqdfields = explode(" ", "descr cert");
540 76d49f20 Renato Botelho
		$reqdfieldsn = array(
541 78863416 Phil Davis
			gettext("Descriptive name"),
542
			gettext("Final Certificate data"));
543 64cc39d3 Matthew Grooms
544 1e9b4611 Renato Botelho
		do_input_validation($_POST, $reqdfields, $reqdfieldsn, $input_errors);
545 64cc39d3 Matthew Grooms
546 b741d2ef jim-p
		if (preg_match("/[\?\>\<\&\/\\\"\']/", $_POST['descr'])) {
547
			array_push($input_errors, "The field 'Descriptive Name' contains invalid characters.");
548
		}
549
550 a828210b yakatz
//		old way
551 64cc39d3 Matthew Grooms
		/* make sure this csr and certificate subjects match */
552 a828210b yakatz
//		$subj_csr = csr_get_subject($pconfig['csr'], false);
553
//		$subj_cert = cert_get_subject($pconfig['cert'], false);
554
//
555 56b1ed39 Phil Davis
//		if (!isset($_POST['ignoresubjectmismatch']) && !($_POST['ignoresubjectmismatch'] == "yes")) {
556
//			if (strcmp($subj_csr, $subj_cert)) {
557
//				$input_errors[] = sprintf(gettext("The certificate subject '%s' does not match the signing request subject."), $subj_cert);
558 a828210b yakatz
//				$subject_mismatch = true;
559
//			}
560
//		}
561 1746c5ce PiBa-NL
		$mod_csr = cert_get_publickey($pconfig['csr'], false, 'csr');
562
		$mod_cert = cert_get_publickey($pconfig['cert'], false);
563 b49f31d0 Sjon Hortensius
564 56b1ed39 Phil Davis
		if (strcmp($mod_csr, $mod_cert)) {
565 a828210b yakatz
			// simply: if the moduli don't match, then the private key and public key won't match
566 1746c5ce PiBa-NL
			$input_errors[] = sprintf(gettext("The certificate public key does not match the signing request public key."), $subj_cert);
567 a828210b yakatz
			$subject_mismatch = true;
568
		}
569 64cc39d3 Matthew Grooms
570
		/* save modifications */
571
		if (!$input_errors) {
572
573
			$cert = $a_cert[$id];
574
575 f2a86ca9 jim-p
			$cert['descr'] = $pconfig['descr'];
576 64cc39d3 Matthew Grooms
577
			csr_complete($cert, $pconfig['cert']);
578
579
			$a_cert[$id] = $cert;
580
581
			write_config();
582
583
			pfSenseHeader("system_certmanager.php");
584
		}
585
	}
586
}
587
588 56c6b1cb k-paulius
$pgtitle = array(gettext("System"), gettext("Certificate Manager"), gettext("Certificates"));
589 edcd7535 Phil Davis
$pglinks = array("", "system_camanager.php", "system_certmanager.php");
590 56c6b1cb k-paulius
591
if (($act == "new" || ($_POST['save'] == gettext("Save") && $input_errors)) || ($act == "csr" || ($_POST['save'] == gettext("Update") && $input_errors))) {
592
	$pgtitle[] = gettext('Edit');
593 edcd7535 Phil Davis
	$pglinks[] = "@self";
594 56c6b1cb k-paulius
}
595 64cc39d3 Matthew Grooms
include("head.inc");
596 b49f31d0 Sjon Hortensius
597 78863416 Phil Davis
if ($input_errors) {
598 b49f31d0 Sjon Hortensius
	print_input_errors($input_errors);
599 78863416 Phil Davis
}
600 0edcccc3 Daniel Seebald
601 78863416 Phil Davis
if ($savemsg) {
602 3f0efd58 Stephen Beaver
	print_info_box($savemsg, 'success');
603 78863416 Phil Davis
}
604 b49f31d0 Sjon Hortensius
605
$tab_array = array();
606
$tab_array[] = array(gettext("CAs"), false, "system_camanager.php");
607
$tab_array[] = array(gettext("Certificates"), true, "system_certmanager.php");
608
$tab_array[] = array(gettext("Certificate Revocation"), false, "system_crlmanager.php");
609
display_top_tabs($tab_array);
610
611
// Load valid country codes
612
$dn_cc = array();
613 78863416 Phil Davis
if (file_exists("/etc/ca_countries")) {
614 b49f31d0 Sjon Hortensius
	$dn_cc_file=file("/etc/ca_countries");
615 78863416 Phil Davis
	foreach ($dn_cc_file as $line) {
616 b8f22f61 Stephen Beaver
		if (preg_match('/^(\S*)\s(.*)$/', $line, $matches)) {
617
			$dn_cc[$matches[1]] = $matches[1];
618
		}
619
	}
620 b49f31d0 Sjon Hortensius
}
621
622 b29c322c Stephen Beaver
if ($act == "new" || (($_POST['save'] == gettext("Save")) && $input_errors)) {
623 b35250d9 NewEraCracker
	$form = new Form();
624
	$form->setAction('system_certmanager.php?act=edit');
625 b49f31d0 Sjon Hortensius
626 b35250d9 NewEraCracker
	if (isset($userid) && $a_user) {
627
		$form->addGlobal(new Form_Input(
628
			'userid',
629
			null,
630
			'hidden',
631
			$userid
632
		));
633
	}
634 b49f31d0 Sjon Hortensius
635 78863416 Phil Davis
	if (isset($id) && $a_cert[$id]) {
636 b49f31d0 Sjon Hortensius
		$form->addGlobal(new Form_Input(
637
			'id',
638
			null,
639
			'hidden',
640
			$id
641
		));
642 64cc39d3 Matthew Grooms
	}
643 b49f31d0 Sjon Hortensius
644 2052d3e2 Steve Beaver
	$section = new Form_Section('Add/Sign a New Certificate');
645 b35250d9 NewEraCracker
646
	if (!isset($id)) {
647
		$section->addInput(new Form_Select(
648
			'method',
649 153c3aa6 Phil Davis
			'*Method',
650 b35250d9 NewEraCracker
			$pconfig['method'],
651
			$cert_methods
652
		))->toggles();
653
	}
654
655 b49f31d0 Sjon Hortensius
	$section->addInput(new Form_Input(
656
		'descr',
657 153c3aa6 Phil Davis
		'*Descriptive name',
658 b49f31d0 Sjon Hortensius
		'text',
659 b35250d9 NewEraCracker
		($a_user && empty($pconfig['descr'])) ? $a_user[$userid]['name'] : $pconfig['descr']
660
	))->addClass('toggle-existing');
661 b49f31d0 Sjon Hortensius
662 b35250d9 NewEraCracker
	$form->add($section);
663 2052d3e2 Steve Beaver
664 d520da31 Steve Beaver
	// Return an array containing the IDs od all CAs
665 2052d3e2 Steve Beaver
	function list_cas() {
666
		global $a_ca;
667
		$allCas = array();
668
669
		foreach ($a_ca as $ca) {
670
			if ($ca['prv']) {
671 d520da31 Steve Beaver
				$allCas[$ca['refid']] = $ca['descr'];
672 2052d3e2 Steve Beaver
			}
673
		}
674
675
		return $allCas;
676
	}
677
678 d520da31 Steve Beaver
	// Return an array containing the IDs od all CSRs
679 2052d3e2 Steve Beaver
	function list_csrs() {
680
		global $config;
681
		$allCsrs = array();
682
683
		foreach ($config['cert'] as $cert) {
684
			if ($cert['csr']) {
685 d520da31 Steve Beaver
				$allCsrs[$cert['refid']] = $cert['descr'];
686 2052d3e2 Steve Beaver
			}
687
		}
688
689 d6107e1a Steve Beaver
		return ['new' => gettext('New CSR (Paste below)')] + $allCsrs;
690 2052d3e2 Steve Beaver
	}
691
692
	$section = new Form_Section('Sign CSR');
693
	$section->addClass('toggle-sign collapse');
694
695
	$section->AddInput(new Form_Select(
696
		'catosignwith',
697
		'*CA to sign with',
698
		$pconfig['catosignwith'],
699
		list_cas()
700
	));
701
702
	$section->AddInput(new Form_Select(
703
		'csrtosign',
704
		'*CSR to sign',
705
		isset($pconfig['csrtosign']) ? $pconfig['csrtosign'] : 'new',
706
		list_csrs()
707
	));
708
709
	$section->addInput(new Form_Textarea(
710
		'csrpaste',
711
		'CSR data',
712
		$pconfig['csrpaste']
713
	))->setHelp('Paste a Certificate Signing Request in X.509 PEM format here.');
714
715 55047259 Steve Beaver
	$section->addInput(new Form_Textarea(
716
		'keypaste',
717
		'Key data',
718
		$pconfig['keypaste']
719
	))->setHelp('Optionally paste a private key here. The key will be associated with the newly signed certificate in pfSense');
720
721 0c82b8c2 jim-p
	$section->addInput(new Form_Input(
722
		'csrsign_lifetime',
723
		'*Certificate Lifetime (days)',
724
		'number',
725 aec3a259 jim-p
		$pconfig['csrsign_lifetime'] ? $pconfig['csrsign_lifetime']:'3650'
726 0c82b8c2 jim-p
	));
727 aec3a259 jim-p
	$section->addInput(new Form_Select(
728
		'csrsign_digest_alg',
729
		'*Digest Algorithm',
730
		$pconfig['csrsign_digest_alg'],
731
		array_combine($openssl_digest_algs, $openssl_digest_algs)
732
	))->setHelp('NOTE: It is recommended to use an algorithm stronger than '.
733
		'SHA1 when possible');
734 0c82b8c2 jim-p
735 2052d3e2 Steve Beaver
	$form->add($section);
736
737 b35250d9 NewEraCracker
	$section = new Form_Section('Import Certificate');
738
	$section->addClass('toggle-import collapse');
739 b49f31d0 Sjon Hortensius
740
	$section->addInput(new Form_Textarea(
741
		'cert',
742 153c3aa6 Phil Davis
		'*Certificate data',
743 78863416 Phil Davis
		$pconfig['cert']
744 b35250d9 NewEraCracker
	))->setHelp('Paste a certificate in X.509 PEM format here.');
745
746
	$section->addInput(new Form_Textarea(
747
		'key',
748 153c3aa6 Phil Davis
		'*Private key data',
749 b35250d9 NewEraCracker
		$pconfig['key']
750
	))->setHelp('Paste a private key in X.509 PEM format here.');
751 b49f31d0 Sjon Hortensius
752
	$form->add($section);
753 b35250d9 NewEraCracker
	$section = new Form_Section('Internal Certificate');
754
	$section->addClass('toggle-internal collapse');
755
756
	if (!$internal_ca_count) {
757
		$section->addInput(new Form_StaticText(
758 153c3aa6 Phil Davis
			'*Certificate authority',
759 781d9ce4 Phil Davis
			gettext('No internal Certificate Authorities have been defined. ') .
760
			gettext('An internal CA must be defined in order to create an internal certificate. ') .
761
			sprintf(gettext('%1$sCreate%2$s an internal CA.'), '<a href="system_camanager.php?act=new&amp;method=internal"> ', '</a>')
762 b35250d9 NewEraCracker
		));
763
	} else {
764
		$allCas = array();
765
		foreach ($a_ca as $ca) {
766
			if (!$ca['prv']) {
767
				continue;
768
			}
769 b49f31d0 Sjon Hortensius
770 b35250d9 NewEraCracker
			$allCas[ $ca['refid'] ] = $ca['descr'];
771
		}
772 64cc39d3 Matthew Grooms
773 b35250d9 NewEraCracker
		$section->addInput(new Form_Select(
774
			'caref',
775 153c3aa6 Phil Davis
			'*Certificate authority',
776 b35250d9 NewEraCracker
			$pconfig['caref'],
777
			$allCas
778
		));
779
	}
780 64cc39d3 Matthew Grooms
781 b35250d9 NewEraCracker
	$section->addInput(new Form_Select(
782
		'keylen',
783 153c3aa6 Phil Davis
		'*Key length',
784 b35250d9 NewEraCracker
		$pconfig['keylen'],
785
		array_combine($cert_keylens, $cert_keylens)
786 b49f31d0 Sjon Hortensius
	));
787 64cc39d3 Matthew Grooms
788 b35250d9 NewEraCracker
	$section->addInput(new Form_Select(
789
		'digest_alg',
790 153c3aa6 Phil Davis
		'*Digest Algorithm',
791 b35250d9 NewEraCracker
		$pconfig['digest_alg'],
792
		array_combine($openssl_digest_algs, $openssl_digest_algs)
793
	))->setHelp('NOTE: It is recommended to use an algorithm stronger than '.
794
		'SHA1 when possible.');
795 b49f31d0 Sjon Hortensius
796 b35250d9 NewEraCracker
	$section->addInput(new Form_Input(
797
		'lifetime',
798 153c3aa6 Phil Davis
		'*Lifetime (days)',
799 b35250d9 NewEraCracker
		'number',
800
		$pconfig['lifetime']
801
	));
802 b49f31d0 Sjon Hortensius
803
	$section->addInput(new Form_Select(
804 b35250d9 NewEraCracker
		'dn_country',
805 153c3aa6 Phil Davis
		'*Country Code',
806 b35250d9 NewEraCracker
		$pconfig['dn_country'],
807
		$dn_cc
808 b49f31d0 Sjon Hortensius
	));
809
810 b35250d9 NewEraCracker
	$section->addInput(new Form_Input(
811
		'dn_state',
812 153c3aa6 Phil Davis
		'*State or Province',
813 b35250d9 NewEraCracker
		'text',
814
		$pconfig['dn_state'],
815
		['placeholder' => 'e.g. Texas']
816 b49f31d0 Sjon Hortensius
	));
817
818 b35250d9 NewEraCracker
	$section->addInput(new Form_Input(
819
		'dn_city',
820 153c3aa6 Phil Davis
		'*City',
821 b35250d9 NewEraCracker
		'text',
822
		$pconfig['dn_city'],
823
		['placeholder' => 'e.g. Austin']
824
	));
825
826
	$section->addInput(new Form_Input(
827
		'dn_organization',
828 153c3aa6 Phil Davis
		'*Organization',
829 b35250d9 NewEraCracker
		'text',
830
		$pconfig['dn_organization'],
831 da0f70ed jim-p
		['placeholder' => 'e.g. My Company Inc']
832
	));
833
834
	$section->addInput(new Form_Input(
835
		'dn_organizationalunit',
836
		'Organizational Unit',
837
		'text',
838
		$pconfig['dn_organizationalunit'],
839
		['placeholder' => 'e.g. My Department Name (optional)']
840 b35250d9 NewEraCracker
	));
841
842
	$section->addInput(new Form_Input(
843
		'dn_email',
844 153c3aa6 Phil Davis
		'*Email Address',
845 b35250d9 NewEraCracker
		'text',
846
		$pconfig['dn_email'],
847
		['placeholder' => 'e.g. admin@mycompany.com']
848
	));
849
850
	$section->addInput(new Form_Input(
851
		'dn_commonname',
852 153c3aa6 Phil Davis
		'*Common Name',
853 b35250d9 NewEraCracker
		'text',
854
		$pconfig['dn_commonname'],
855
		['placeholder' => 'e.g. www.example.com']
856
	));
857
858
	$form->add($section);
859
	$section = new Form_Section('External Signing Request');
860
	$section->addClass('toggle-external collapse');
861
862 b49f31d0 Sjon Hortensius
	$section->addInput(new Form_Select(
863 b35250d9 NewEraCracker
		'csr_keylen',
864 153c3aa6 Phil Davis
		'*Key length',
865 b35250d9 NewEraCracker
		$pconfig['csr_keylen'],
866
		array_combine($cert_keylens, $cert_keylens)
867 b49f31d0 Sjon Hortensius
	));
868 64cc39d3 Matthew Grooms
869 b35250d9 NewEraCracker
	$section->addInput(new Form_Select(
870
		'csr_digest_alg',
871 153c3aa6 Phil Davis
		'*Digest Algorithm',
872 b35250d9 NewEraCracker
		$pconfig['csr_digest_alg'],
873
		array_combine($openssl_digest_algs, $openssl_digest_algs)
874
	))->setHelp('NOTE: It is recommended to use an algorithm stronger than '.
875
		'SHA1 when possible');
876 b49f31d0 Sjon Hortensius
877 b35250d9 NewEraCracker
	$section->addInput(new Form_Select(
878
		'csr_dn_country',
879 153c3aa6 Phil Davis
		'*Country Code',
880 b35250d9 NewEraCracker
		$pconfig['csr_dn_country'],
881
		$dn_cc
882
	));
883 bf9d50e8 Stephen Beaver
884 b35250d9 NewEraCracker
	$section->addInput(new Form_Input(
885
		'csr_dn_state',
886 153c3aa6 Phil Davis
		'*State or Province',
887 b35250d9 NewEraCracker
		'text',
888
		$pconfig['csr_dn_state'],
889
		['placeholder' => 'e.g. Texas']
890
	));
891 bf9d50e8 Stephen Beaver
892 b35250d9 NewEraCracker
	$section->addInput(new Form_Input(
893
		'csr_dn_city',
894 153c3aa6 Phil Davis
		'*City',
895 b35250d9 NewEraCracker
		'text',
896
		$pconfig['csr_dn_city'],
897
		['placeholder' => 'e.g. Austin']
898
	));
899 bf9d50e8 Stephen Beaver
900 b35250d9 NewEraCracker
	$section->addInput(new Form_Input(
901
		'csr_dn_organization',
902 153c3aa6 Phil Davis
		'*Organization',
903 b35250d9 NewEraCracker
		'text',
904
		$pconfig['csr_dn_organization'],
905 da0f70ed jim-p
		['placeholder' => 'e.g. My Company Inc']
906
	));
907
908
	$section->addInput(new Form_Input(
909
		'csr_dn_organizationalunit',
910
		'Organizational Unit',
911
		'text',
912
		$pconfig['csr_dn_organizationalunit'],
913
		['placeholder' => 'e.g. My Department Name (optional)']
914 b35250d9 NewEraCracker
	));
915 b49f31d0 Sjon Hortensius
916 b35250d9 NewEraCracker
	$section->addInput(new Form_Input(
917
		'csr_dn_email',
918 153c3aa6 Phil Davis
		'*Email Address',
919 b49f31d0 Sjon Hortensius
		'text',
920 b35250d9 NewEraCracker
		$pconfig['csr_dn_email'],
921
		['placeholder' => 'e.g. admin@mycompany.com']
922
	));
923 bf9d50e8 Stephen Beaver
924 b35250d9 NewEraCracker
	$section->addInput(new Form_Input(
925
		'csr_dn_commonname',
926 153c3aa6 Phil Davis
		'*Common Name',
927 b35250d9 NewEraCracker
		'text',
928
		$pconfig['csr_dn_commonname'],
929
		['placeholder' => 'e.g. internal-ca']
930
	));
931 bf9d50e8 Stephen Beaver
932 0c82b8c2 jim-p
	$form->add($section);
933
	$section = new Form_Section('Choose an Existing Certificate');
934
	$section->addClass('toggle-existing collapse');
935
936
	$existCerts = array();
937
938
	foreach ($config['cert'] as $cert)	{
939
		if (is_array($config['system']['user'][$userid]['cert'])) { // Could be MIA!
940
			if (isset($userid) && in_array($cert['refid'], $config['system']['user'][$userid]['cert'])) {
941
				continue;
942
			}
943
		}
944
945
		$ca = lookup_ca($cert['caref']);
946
		if ($ca) {
947
			$cert['descr'] .= " (CA: {$ca['descr']})";
948
		}
949
950
		if (cert_in_use($cert['refid'])) {
951
			$cert['descr'] .= " (In Use)";
952
		}
953
		if (is_cert_revoked($cert)) {
954
			$cert['descr'] .= " (Revoked)";
955
		}
956
957
		$existCerts[ $cert['refid'] ] = $cert['descr'];
958
	}
959
960
	$section->addInput(new Form_Select(
961
		'certref',
962
		'*Existing Certificates',
963
		$pconfig['certref'],
964
		$existCerts
965
	));
966
967
	$form->add($section);
968
969
	$section = new Form_Section('Certificate Attributes');
970
	$section->addClass('toggle-external toggle-internal toggle-sign collapse');
971
972
	$section->addInput(new Form_StaticText(
973
		gettext('Attribute Notes'),
974
		'<span class="help-block">'.
975
		gettext('The following attributes are added to certificates and ' .
976
		'requests when they are created or signed. These attributes behave ' .
977
		'differently depending on the selected mode.') .
978
		'<br/><br/>' .
979
		'<span class="toggle-internal collapse">' . gettext('For Internal Certificates, these attributes are added directly to the certificate as shown.') . '</span>' .
980
		'<span class="toggle-external collapse">' .
981
		gettext('For Certificate Signing Requests, These attributes are added to the request but they may be ignored or changed by the CA that signs the request. ') .
982
		'<br/><br/>' .
983
		gettext('If this CSR will be signed using the Certificate Manager on this firewall, set the attributes when signing instead as they cannot be carried over.') . '</span>' .
984
		'<span class="toggle-sign collapse">' . gettext('When Signing a Certificate Request, existing attributes in the request cannot be copied. The attributes below will be applied to the resulting certificate.') . '</span>' .
985
		'</span>'
986
	));
987
988
	$section->addInput(new Form_Select(
989
		'type',
990
		'*Certificate Type',
991
		$pconfig['type'],
992
		$cert_types
993
	))->setHelp('Add type-specific usage attributes to the signed certificate.' .
994
		' Used for placing usage restrictions on, or granting abilities to, ' .
995
		'the signed certificate.');
996
997 282b6c66 jim-p
	if (empty($pconfig['altnames']['item'])) {
998
		$pconfig['altnames']['item'] = array(
999
			array('type' => null, 'value' => null)
1000
		);
1001
	}
1002
1003
	$counter = 0;
1004
	$numrows = count($pconfig['altnames']['item']) - 1;
1005
1006
	foreach ($pconfig['altnames']['item'] as $item) {
1007
1008
		$group = new Form_Group($counter == 0 ? 'Alternative Names':'');
1009
1010
		$group->add(new Form_Select(
1011
			'altname_type' . $counter,
1012
			'Type',
1013
			$item['type'],
1014
			$cert_altname_types
1015
		))->setHelp(($counter == $numrows) ? 'Type':null);
1016
1017
		$group->add(new Form_Input(
1018
			'altname_value' . $counter,
1019
			null,
1020
			'text',
1021
			$item['value']
1022
		))->setHelp(($counter == $numrows) ? 'Value':null);
1023
1024
		$group->add(new Form_Button(
1025
			'deleterow' . $counter,
1026
			'Delete',
1027
			null,
1028
			'fa-trash'
1029
		))->addClass('btn-warning');
1030
1031
		$group->addClass('repeatable');
1032
1033 0c82b8c2 jim-p
		$group->setHelp('Enter additional identifiers for the certificate ' .
1034
			'in this list. The Common Name field is automatically ' .
1035
			'added to the certificate as an Alternative Name. ' .
1036
			'The signing CA may ignore or change these values.');
1037 282b6c66 jim-p
1038
		$section->add($group);
1039
1040
		$counter++;
1041
	}
1042
1043
	$section->addInput(new Form_Button(
1044
		'addrow',
1045
		'Add',
1046
		null,
1047
		'fa-plus'
1048
	))->addClass('btn-success');
1049
1050 b35250d9 NewEraCracker
	$form->add($section);
1051 b49f31d0 Sjon Hortensius
1052
1053 b35250d9 NewEraCracker
	print $form;
1054 64cc39d3 Matthew Grooms
1055 b29c322c Stephen Beaver
} else if ($act == "csr" || (($_POST['save'] == gettext("Update")) && $input_errors)) {
1056 8f58b51b jim-p
	$form = new Form(false);
1057 308f0665 NewEraCracker
	$form->setAction('system_certmanager.php?act=csr');
1058 b29c322c Stephen Beaver
1059 5f88f964 k-paulius
	$section = new Form_Section("Complete Signing Request for " . $pconfig['descr']);
1060 b29c322c Stephen Beaver
1061 ba5c55e9 Stephen Beaver
	$section->addInput(new Form_Input(
1062
		'descr',
1063 153c3aa6 Phil Davis
		'*Descriptive name',
1064 ba5c55e9 Stephen Beaver
		'text',
1065
		$pconfig['descr']
1066
	));
1067
1068 b29c322c Stephen Beaver
	$section->addInput(new Form_Textarea(
1069
		'csr',
1070
		'Signing request data',
1071
		$pconfig['csr']
1072
	))->setReadonly()
1073 af28e231 Stephen Beaver
	  ->setWidth(7)
1074 813c6673 NOYB
	  ->setHelp('Copy the certificate signing data from here and forward it to a certificate authority for signing.');
1075 b29c322c Stephen Beaver
1076
	$section->addInput(new Form_Textarea(
1077
		'cert',
1078 153c3aa6 Phil Davis
		'*Final certificate data',
1079 b29c322c Stephen Beaver
		$pconfig['cert']
1080 af28e231 Stephen Beaver
	))->setWidth(7)
1081 813c6673 NOYB
	  ->setHelp('Paste the certificate received from the certificate authority here.');
1082 b29c322c Stephen Beaver
1083
	 if (isset($id) && $a_cert[$id]) {
1084
		 $section->addInput(new Form_Input(
1085
			'id',
1086
			null,
1087
			'hidden',
1088
			$id
1089
		 ));
1090
1091
		 $section->addInput(new Form_Input(
1092
			'act',
1093
			null,
1094
			'hidden',
1095
			'csr'
1096
		 ));
1097
	 }
1098
1099
	$form->add($section);
1100 8f58b51b jim-p
1101
	$form->addGlobal(new Form_Button(
1102 141d8913 jim-p
		'save',
1103 faab522f Renato Botelho
		'Update',
1104 8f58b51b jim-p
		null,
1105
		'fa-save'
1106
	))->addClass('btn-primary');
1107
1108 b29c322c Stephen Beaver
	print($form);
1109
} else {
1110
?>
1111 060ed238 Stephen Beaver
<div class="panel panel-default">
1112
	<div class="panel-heading"><h2 class="panel-title"><?=gettext('Certificates')?></h2></div>
1113
	<div class="panel-body">
1114
		<div class="table-responsive">
1115
		<table class="table table-striped table-hover">
1116
			<thead>
1117
				<tr>
1118
					<th><?=gettext("Name")?></th>
1119
					<th><?=gettext("Issuer")?></th>
1120
					<th><?=gettext("Distinguished Name")?></th>
1121
					<th><?=gettext("In Use")?></th>
1122 4db1f211 Stephen Beaver
1123 060ed238 Stephen Beaver
					<th class="col-sm-2"><?=gettext("Actions")?></th>
1124
				</tr>
1125
			</thead>
1126
			<tbody>
1127 b29c322c Stephen Beaver
<?php
1128 4db1f211 Stephen Beaver
1129
$pluginparams = array();
1130
$pluginparams['type'] = 'certificates';
1131
$pluginparams['event'] = 'used_certificates';
1132
$certificates_used_by_packages = pkg_call_plugins('plugin_certificates', $pluginparams);
1133
$i = 0;
1134 78863416 Phil Davis
foreach ($a_cert as $i => $cert):
1135 b29c322c Stephen Beaver
	$name = htmlspecialchars($cert['descr']);
1136 00d5594c jim-p
	$sans = array();
1137 b29c322c Stephen Beaver
	if ($cert['crt']) {
1138
		$subj = cert_get_subject($cert['crt']);
1139
		$issuer = cert_get_issuer($cert['crt']);
1140
		$purpose = cert_get_purpose($cert['crt']);
1141 4906f4ee jim-p
		$sans = cert_get_sans($cert['crt']);
1142 b29c322c Stephen Beaver
		list($startdate, $enddate) = cert_get_dates($cert['crt']);
1143
1144 78863416 Phil Davis
		if ($subj == $issuer) {
1145 b29c322c Stephen Beaver
			$caname = '<i>'. gettext("self-signed") .'</i>';
1146 78863416 Phil Davis
		} else {
1147 b29c322c Stephen Beaver
			$caname = '<i>'. gettext("external").'</i>';
1148 78863416 Phil Davis
		}
1149 b29c322c Stephen Beaver
1150 83d2b83a jim-p
		$subj = htmlspecialchars(cert_escape_x509_chars($subj, true));
1151 1048585a PiBa-NL
	} else {
1152
		$subj = "";
1153
		$issuer = "";
1154
		$purpose = "";
1155
		$startdate = "";
1156
		$enddate = "";
1157
		$caname = "<em>" . gettext("private key only") . "</em>";
1158 b29c322c Stephen Beaver
	}
1159
1160
	if ($cert['csr']) {
1161 83d2b83a jim-p
		$subj = htmlspecialchars(cert_escape_x509_chars(csr_get_subject($cert['csr']), true));
1162 4906f4ee jim-p
		$sans = cert_get_sans($cert['crt']);
1163 b29c322c Stephen Beaver
		$caname = "<em>" . gettext("external - signature pending") . "</em>";
1164
	}
1165
1166
	$ca = lookup_ca($cert['caref']);
1167 78863416 Phil Davis
	if ($ca) {
1168 b29c322c Stephen Beaver
		$caname = $ca['descr'];
1169 78863416 Phil Davis
	}
1170 b29c322c Stephen Beaver
?>
1171 060ed238 Stephen Beaver
				<tr>
1172
					<td>
1173
						<?=$name?><br />
1174
						<?php if ($cert['type']): ?>
1175
							<i><?=$cert_types[$cert['type']]?></i><br />
1176
						<?php endif?>
1177
						<?php if (is_array($purpose)): ?>
1178 4906f4ee jim-p
							CA: <b><?=$purpose['ca']?></b><br/>
1179
							<?=gettext("Server")?>: <b><?=$purpose['server']?></b><br/>
1180 060ed238 Stephen Beaver
						<?php endif?>
1181
					</td>
1182
					<td><?=$caname?></td>
1183
					<td>
1184
						<?=$subj?>
1185 4906f4ee jim-p
						<?php
1186
						$certextinfo = "";
1187 aec3a259 jim-p
						$certserial = cert_get_serial($cert['crt']);
1188
						if (!empty($certserial)) {
1189
							$certextinfo .= '<b>' . gettext("Serial: ") . '</b> ';
1190
							$certextinfo .= htmlspecialchars(cert_escape_x509_chars($certserial, true));
1191
							$certextinfo .= '<br/>';
1192
						}
1193
						$certsig = cert_get_sigtype($cert['crt']);
1194
						if (is_array($certsig) && !empty($certsig) && !empty($certsig['shortname'])) {
1195
							$certextinfo .= '<b>' . gettext("Signature Digest: ") . '</b> ';
1196
							$certextinfo .= htmlspecialchars(cert_escape_x509_chars($certsig['shortname'], true));
1197
							$certextinfo .= '<br/>';
1198
						}
1199 4906f4ee jim-p
						if (is_array($sans) && !empty($sans)) {
1200
							$certextinfo .= '<b>' . gettext("SAN: ") . '</b> ';
1201 2e1809dd jim-p
							$certextinfo .= htmlspecialchars(implode(', ', cert_escape_x509_chars($sans, true)));
1202 4906f4ee jim-p
							$certextinfo .= '<br/>';
1203
						}
1204
						if (is_array($purpose) && !empty($purpose['ku'])) {
1205
							$certextinfo .= '<b>' . gettext("KU: ") . '</b> ';
1206
							$certextinfo .= htmlspecialchars(implode(', ', $purpose['ku']));
1207
							$certextinfo .= '<br/>';
1208
						}
1209
						if (is_array($purpose) && !empty($purpose['eku'])) {
1210
							$certextinfo .= '<b>' . gettext("EKU: ") . '</b> ';
1211
							$certextinfo .= htmlspecialchars(implode(', ', $purpose['eku']));
1212
						}
1213
						?>
1214
						<?php if (!empty($certextinfo)): ?>
1215
							<div class="infoblock">
1216
							<? print_info_box($certextinfo, 'info', false); ?>
1217
							</div>
1218
						<?php endif?>
1219
1220
						<?php if (!empty($startdate) || !empty($enddate)): ?>
1221 b090c741 jim-p
						<br />
1222 060ed238 Stephen Beaver
						<small>
1223
							<?=gettext("Valid From")?>: <b><?=$startdate ?></b><br /><?=gettext("Valid Until")?>: <b><?=$enddate ?></b>
1224
						</small>
1225
						<?php endif?>
1226
					</td>
1227
					<td>
1228
						<?php if (is_cert_revoked($cert)): ?>
1229 762faef5 Phil Davis
							<i><?=gettext("Revoked")?></i>
1230 060ed238 Stephen Beaver
						<?php endif?>
1231
						<?php if (is_webgui_cert($cert['refid'])): ?>
1232 762faef5 Phil Davis
							<?=gettext("webConfigurator")?>
1233 060ed238 Stephen Beaver
						<?php endif?>
1234
						<?php if (is_user_cert($cert['refid'])): ?>
1235 762faef5 Phil Davis
							<?=gettext("User Cert")?>
1236 060ed238 Stephen Beaver
						<?php endif?>
1237
						<?php if (is_openvpn_server_cert($cert['refid'])): ?>
1238 762faef5 Phil Davis
							<?=gettext("OpenVPN Server")?>
1239 060ed238 Stephen Beaver
						<?php endif?>
1240
						<?php if (is_openvpn_client_cert($cert['refid'])): ?>
1241 762faef5 Phil Davis
							<?=gettext("OpenVPN Client")?>
1242 060ed238 Stephen Beaver
						<?php endif?>
1243
						<?php if (is_ipsec_cert($cert['refid'])): ?>
1244 762faef5 Phil Davis
							<?=gettext("IPsec Tunnel")?>
1245 060ed238 Stephen Beaver
						<?php endif?>
1246
						<?php if (is_captiveportal_cert($cert['refid'])): ?>
1247 762faef5 Phil Davis
							<?=gettext("Captive Portal")?>
1248 060ed238 Stephen Beaver
						<?php endif?>
1249 3bde5cdd PiBa-NL
						<?php echo cert_usedby_description($cert['refid'], $certificates_used_by_packages); ?>
1250 060ed238 Stephen Beaver
					</td>
1251
					<td>
1252
						<?php if (!$cert['csr']): ?>
1253 4611e283 Steve Beaver
							<a href="system_certmanager.php?act=exp&amp;id=<?=$i?>" class="fa fa-certificate" title="<?=gettext("Export Certificate")?>"></a>
1254 4594038a Steve Beaver
							<?php if ($cert['prv']): ?>
1255
								<a href="system_certmanager.php?act=key&amp;id=<?=$i?>" class="fa fa-key" title="<?=gettext("Export Key")?>"></a>
1256
							<?php endif?>
1257 4611e283 Steve Beaver
							<a href="system_certmanager.php?act=p12&amp;id=<?=$i?>" class="fa fa-archive" title="<?=gettext("Export P12")?>"></a>
1258 060ed238 Stephen Beaver
						<?php else: ?>
1259 4611e283 Steve Beaver
							<a href="system_certmanager.php?act=csr&amp;id=<?=$i?>" class="fa fa-pencil" title="<?=gettext("Update CSR")?>"></a>
1260
							<a href="system_certmanager.php?act=req&amp;id=<?=$i?>" class="fa fa-sign-in" title="<?=gettext("Export Request")?>"></a>
1261
							<a href="system_certmanager.php?act=key&amp;id=<?=$i?>" class="fa fa-key" title="<?=gettext("Export Key")?>"></a>
1262 060ed238 Stephen Beaver
						<?php endif?>
1263
						<?php if (!cert_in_use($cert['refid'])): ?>
1264 fe914124 Steve Beaver
							<a href="system_certmanager.php?act=del&amp;id=<?=$i?>" class="fa fa-trash" title="<?=gettext("Delete Certificate")?>" usepost></a>
1265 060ed238 Stephen Beaver
						<?php endif?>
1266
					</td>
1267
				</tr>
1268 4db1f211 Stephen Beaver
<?php
1269 e8afd822 Steve Beaver
	$i++;
1270 4db1f211 Stephen Beaver
	endforeach; ?>
1271 060ed238 Stephen Beaver
			</tbody>
1272
		</table>
1273
		</div>
1274
	</div>
1275 b29c322c Stephen Beaver
</div>
1276
1277
<nav class="action-buttons">
1278 4611e283 Steve Beaver
	<a href="?act=new" class="btn btn-success btn-sm">
1279 b29c322c Stephen Beaver
		<i class="fa fa-plus icon-embed-btn"></i>
1280 2052d3e2 Steve Beaver
		<?=gettext("Add/Sign")?>
1281 b29c322c Stephen Beaver
	</a>
1282
</nav>
1283 e9258698 NewEraCracker
<?php
1284 b29c322c Stephen Beaver
	include("foot.inc");
1285
	exit;
1286
}
1287
1288
1289 51583438 Stephen Beaver
?>
1290 8fd9052f Colin Fleming
<script type="text/javascript">
1291 51583438 Stephen Beaver
//<![CDATA[
1292 78863416 Phil Davis
events.push(function() {
1293 bf9d50e8 Stephen Beaver
1294 51583438 Stephen Beaver
<?php if ($internal_ca_count): ?>
1295
	function internalca_change() {
1296
1297
		caref = $('#caref').val();
1298
1299
		switch (caref) {
1300
<?php
1301
			foreach ($a_ca as $ca):
1302
				if (!$ca['prv']) {
1303
					continue;
1304
				}
1305
1306
				$subject = cert_get_subject_array($ca['crt']);
1307
?>
1308
				case "<?=$ca['refid'];?>":
1309 83d2b83a jim-p
					$('#dn_country').val(<?=json_encode(cert_escape_x509_chars($subject[0]['v'], true));?>);
1310
					$('#dn_state').val(<?=json_encode(cert_escape_x509_chars($subject[1]['v'], true));?>);
1311
					$('#dn_city').val(<?=json_encode(cert_escape_x509_chars($subject[2]['v'], true));?>);
1312
					$('#dn_organization').val(<?=json_encode(cert_escape_x509_chars($subject[3]['v'], true));?>);
1313
					$('#dn_email').val(<?=json_encode(cert_escape_x509_chars($subject[4]['v'], true));?>);
1314
					$('#dn_organizationalunit').val(<?=json_encode(cert_escape_x509_chars($subject[6]['v'], true));?>);
1315 51583438 Stephen Beaver
					break;
1316
<?php
1317
			endforeach;
1318
?>
1319
		}
1320
	}
1321
1322 2052d3e2 Steve Beaver
	function set_csr_ro() {
1323 b078cd59 Steve Beaver
		var newcsr = ($('#csrtosign').val() == "new");
1324 65d735f0 Steve Beaver
1325
		$('#csrpaste').attr('readonly', !newcsr);
1326 55047259 Steve Beaver
		$('#keypaste').attr('readonly', !newcsr);
1327 65d735f0 Steve Beaver
		setRequired('csrpaste', newcsr);
1328 2052d3e2 Steve Beaver
	}
1329
1330 eef93144 Jared Dillard
	// ---------- Click checkbox handlers ---------------------------------------------------------
1331 f74457df Stephen Beaver
1332 51583438 Stephen Beaver
	$('#caref').on('change', function() {
1333
		internalca_change();
1334
	});
1335
1336 2052d3e2 Steve Beaver
	$('#csrtosign').change(function () {
1337
		set_csr_ro();
1338
	});
1339
1340 eef93144 Jared Dillard
	// ---------- On initial page load ------------------------------------------------------------
1341
1342 51583438 Stephen Beaver
	internalca_change();
1343 2052d3e2 Steve Beaver
	set_csr_ro();
1344 51583438 Stephen Beaver
1345 0bc61baa Stephen Beaver
	// Suppress "Delete row" button if there are fewer than two rows
1346
	checkLastRow();
1347
1348 51583438 Stephen Beaver
<?php endif; ?>
1349
1350
1351
});
1352
//]]>
1353
</script>
1354
<?php
1355 0edcccc3 Daniel Seebald
include('foot.inc');