Project

General

Profile

Download (38.7 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 a37753d7 Vinicius Coque
	"internal" => gettext("Create an internal Certificate"),
36 b0a5c280 jim-p
	"import" => gettext("Import an existing 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 36cfae5f Justin Coffman
$cert_keylens = array("1024", "2048", "3072", "4096", "6144", "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 80d50253 jim-p
				"descr caref keylen type lifetime dn_commonname");
251 38fb1109 Vinicius Coque
			$reqdfieldsn = array(
252 56b1ed39 Phil Davis
				gettext("Descriptive name"),
253
				gettext("Certificate authority"),
254
				gettext("Key length"),
255
				gettext("Certificate Type"),
256
				gettext("Lifetime"),
257
				gettext("Distinguished name Common Name"));
258 64cc39d3 Matthew Grooms
		}
259
260
		if ($pconfig['method'] == "external") {
261
			$reqdfields = explode(" ",
262 80d50253 jim-p
				"descr csr_keylen csr_dn_commonname");
263 38fb1109 Vinicius Coque
			$reqdfieldsn = array(
264 56b1ed39 Phil Davis
				gettext("Descriptive name"),
265
				gettext("Key length"),
266
				gettext("Distinguished name Common Name"));
267 64cc39d3 Matthew Grooms
		}
268
269 ad9b5c67 jim-p
		if ($pconfig['method'] == "existing") {
270
			$reqdfields = array("certref");
271
			$reqdfieldsn = array(gettext("Existing Certificate Choice"));
272
		}
273
274 547c56c4 jim-p
		$altnames = array();
275 1e9b4611 Renato Botelho
		do_input_validation($_POST, $reqdfields, $reqdfieldsn, $input_errors);
276 2052d3e2 Steve Beaver
277 eecbeec4 Renato Botelho
		if ($pconfig['method'] != "import" && $pconfig['method'] != "existing") {
278 2f65de89 jim-p
			/* subjectAltNames */
279 0c82b8c2 jim-p
			$san_typevar = 'altname_type';
280
			$san_valuevar = 'altname_value';
281
			// This is just the blank alternate name that is added for display purposes. We don't want to validate/save it
282
			if ($_POST["{$san_valuevar}0"] == "") {
283
				unset($_POST["{$san_typevar}0"]);
284
				unset($_POST["{$san_valuevar}0"]);
285
			}
286 bf9d50e8 Stephen Beaver
			foreach ($_POST as $key => $value) {
287
				$entry = '';
288 0c82b8c2 jim-p
				if (!substr_compare($san_typevar, $key, 0, strlen($san_typevar))) {
289
					$entry = substr($key, strlen($san_typevar));
290 bf9d50e8 Stephen Beaver
					$field = 'type';
291 0c82b8c2 jim-p
				} elseif (!substr_compare($san_valuevar, $key, 0, strlen($san_valuevar))) {
292
					$entry = substr($key, strlen($san_valuevar));
293 bf9d50e8 Stephen Beaver
					$field = 'value';
294
				}
295
296
				if (ctype_digit($entry)) {
297 3f0efd58 Stephen Beaver
					$entry++;	// Pre-bootstrap code is one-indexed, but the bootstrap code is 0-indexed
298 bf9d50e8 Stephen Beaver
					$altnames[$entry][$field] = $value;
299
				}
300 2f65de89 jim-p
			}
301 bf9d50e8 Stephen Beaver
302 edf37d56 Renato Botelho
			$pconfig['altnames']['item'] = $altnames;
303 2f65de89 jim-p
304
			/* Input validation for subjectAltNames */
305
			foreach ($altnames as $idx => $altname) {
306
				switch ($altname['type']) {
307
					case "DNS":
308 19a1cf34 jim-p
						if (!is_hostname($altname['value'], true) || is_ipaddr($altname['value'])) {
309 0edcccc3 Daniel Seebald
							array_push($input_errors, "DNS subjectAltName values must be valid hostnames, FQDNs or wildcard domains.");
310 56b1ed39 Phil Davis
						}
311 2f65de89 jim-p
						break;
312
					case "IP":
313 56b1ed39 Phil Davis
						if (!is_ipaddr($altname['value'])) {
314 2f65de89 jim-p
							array_push($input_errors, "IP subjectAltName values must be valid IP Addresses");
315 56b1ed39 Phil Davis
						}
316 2f65de89 jim-p
						break;
317
					case "email":
318 56b1ed39 Phil Davis
						if (empty($altname['value'])) {
319 813c6673 NOYB
							array_push($input_errors, "An e-mail address must be provided for this type of subjectAltName");
320 56b1ed39 Phil Davis
						}
321
						if (preg_match("/[\!\#\$\%\^\(\)\~\?\>\<\&\/\\\,\"\']/", $altname['value'])) {
322 2f65de89 jim-p
							array_push($input_errors, "The e-mail provided in a subjectAltName contains invalid characters.");
323 56b1ed39 Phil Davis
						}
324 2f65de89 jim-p
						break;
325
					case "URI":
326
						/* Close enough? */
327 56b1ed39 Phil Davis
						if (!is_URL($altname['value'])) {
328 2f65de89 jim-p
							$input_errors[] = "URI subjectAltName types must be a valid URI";
329 56b1ed39 Phil Davis
						}
330 2f65de89 jim-p
						break;
331
					default:
332
						$input_errors[] = "Unrecognized subjectAltName type.";
333
				}
334
			}
335
336 21cc2faa Evgeny Yurchenko
			/* Make sure we do not have invalid characters in the fields for the certificate */
337 b741d2ef jim-p
338
			if (preg_match("/[\?\>\<\&\/\\\"\']/", $_POST['descr'])) {
339
				array_push($input_errors, "The field 'Descriptive Name' contains invalid characters.");
340
			}
341
342 56b1ed39 Phil Davis
			if (($pconfig['method'] != "external") && isset($_POST["keylen"]) && !in_array($_POST["keylen"], $cert_keylens)) {
343 741d748d jim-p
				array_push($input_errors, gettext("Please select a valid Key Length."));
344 56b1ed39 Phil Davis
			}
345
			if (($pconfig['method'] != "external") && !in_array($_POST["digest_alg"], $openssl_digest_algs)) {
346 8f07b51c PiBa-NL
				array_push($input_errors, gettext("Please select a valid Digest Algorithm."));
347 56b1ed39 Phil Davis
			}
348 b49f31d0 Sjon Hortensius
349 56b1ed39 Phil Davis
			if (($pconfig['method'] == "external") && isset($_POST["csr_keylen"]) && !in_array($_POST["csr_keylen"], $cert_keylens)) {
350 ca621902 jim-p
				array_push($input_errors, gettext("Please select a valid Key Length."));
351 56b1ed39 Phil Davis
			}
352
			if (($pconfig['method'] == "external") && !in_array($_POST["csr_digest_alg"], $openssl_digest_algs)) {
353 ca621902 jim-p
				array_push($input_errors, gettext("Please select a valid Digest Algorithm."));
354 56b1ed39 Phil Davis
			}
355 aec3a259 jim-p
			if (($pconfig['method'] == "sign") && !in_array($_POST["csrsign_digest_alg"], $openssl_digest_algs)) {
356
				array_push($input_errors, gettext("Please select a valid Digest Algorithm."));
357
			}
358 547c56c4 jim-p
		}
359 64cc39d3 Matthew Grooms
360
		/* save modifications */
361
		if (!$input_errors) {
362
363 ad9b5c67 jim-p
			if ($pconfig['method'] == "existing") {
364
				$cert = lookup_cert($pconfig['certref']);
365 56b1ed39 Phil Davis
				if ($cert && $a_user) {
366 ad9b5c67 jim-p
					$a_user[$userid]['cert'][] = $cert['refid'];
367 56b1ed39 Phil Davis
				}
368 2052d3e2 Steve Beaver
			} else if ($pconfig['method'] == "sign") { // Sign a CSR
369 d520da31 Steve Beaver
				$csrid = lookup_cert($pconfig['csrtosign']);
370 2504e3f1 jim-p
				$ca = & lookup_ca($pconfig['catosignwith']);
371 d520da31 Steve Beaver
372
				// Read the CSR from $config, or if a new one, from the textarea
373 2052d3e2 Steve Beaver
				if ($pconfig['csrtosign'] === "new") {
374
					$csr = $pconfig['csrpaste'];
375
				} else {
376 d520da31 Steve Beaver
					$csr = base64_decode($csrid['csr']);
377 2052d3e2 Steve Beaver
				}
378 0c82b8c2 jim-p
				if (count($altnames)) {
379
					foreach ($altnames as $altname) {
380
						$altnames_tmp[] = "{$altname['type']}:" . cert_escape_x509_chars($altname['value']);
381
					}
382
					$altname_str = implode(",", $altnames_tmp);
383 55047259 Steve Beaver
				}
384 2052d3e2 Steve Beaver
385 aec3a259 jim-p
				$n509 = csr_sign($csr, $ca, $pconfig['csrsign_lifetime'], $pconfig['type'], $altname_str, $pconfig['csrsign_digest_alg']);
386 0c82b8c2 jim-p
387
				if ($n509) {
388
					// Gather the details required to save the new cert
389
					$newcert = array();
390
					$newcert['refid'] = uniqid();
391
					$newcert['caref'] = $pconfig['catosignwith'];
392
					$newcert['descr'] = $pconfig['descr'];
393
					$newcert['type'] = $pconfig['type'];
394
					$newcert['crt'] = base64_encode($n509);
395
396
					if ($pconfig['csrtosign'] === "new") {
397
						$newcert['prv'] = base64_encode($pconfig['keypaste']);
398
					} else {
399
						$newcert['prv'] = $csrid['prv'];
400
					}
401 b078cd59 Steve Beaver
402 0c82b8c2 jim-p
					// Add it to the config file
403
					$config['cert'][] = $newcert;
404
				}
405 2052d3e2 Steve Beaver
406 ad9b5c67 jim-p
			} else {
407
				$cert = array();
408
				$cert['refid'] = uniqid();
409 56b1ed39 Phil Davis
				if (isset($id) && $a_cert[$id]) {
410 ad9b5c67 jim-p
					$cert = $a_cert[$id];
411 56b1ed39 Phil Davis
				}
412 ad9b5c67 jim-p
413 f2a86ca9 jim-p
				$cert['descr'] = $pconfig['descr'];
414 ad9b5c67 jim-p
415 f416763b Phil Davis
				$old_err_level = error_reporting(0); /* otherwise openssl_ functions throw warnings directly to a page screwing menu tab */
416 22b380aa Evgeny Yurchenko
417 56b1ed39 Phil Davis
				if ($pconfig['method'] == "import") {
418 ad9b5c67 jim-p
					cert_import($cert, $pconfig['cert'], $pconfig['key']);
419 56b1ed39 Phil Davis
				}
420 ad9b5c67 jim-p
421
				if ($pconfig['method'] == "internal") {
422 80d50253 jim-p
					$dn = array('commonName' => cert_escape_x509_chars($pconfig['dn_commonname']));
423
					if (!empty($pconfig['dn_country'])) {
424
						$dn['countryName'] = $pconfig['dn_country'];
425
					}
426
					if (!empty($pconfig['dn_state'])) {
427
						$dn['stateOrProvinceName'] = cert_escape_x509_chars($pconfig['dn_state']);
428
					}
429
					if (!empty($pconfig['dn_city'])) {
430
						$dn['localityName'] = cert_escape_x509_chars($pconfig['dn_city']);
431
					}
432
					if (!empty($pconfig['dn_organization'])) {
433
						$dn['organizationName'] = cert_escape_x509_chars($pconfig['dn_organization']);
434
					}
435 da0f70ed jim-p
					if (!empty($pconfig['dn_organizationalunit'])) {
436 83d2b83a jim-p
						$dn['organizationalUnitName'] = cert_escape_x509_chars($pconfig['dn_organizationalunit']);
437 da0f70ed jim-p
					}
438 e562fca2 jim-p
439
					$altnames_tmp = array();
440
					$cn_altname = cert_add_altname_type($pconfig['dn_commonname']);
441
					if (!empty($cn_altname)) {
442
						$altnames_tmp[] = $cn_altname;
443
					}
444 2f65de89 jim-p
					if (count($altnames)) {
445
						foreach ($altnames as $altname) {
446 a636256c jim-p
							// The CN is added as a SAN automatically, do not add it again.
447
							if ($altname['value'] != $pconfig['dn_commonname']) {
448 2e1809dd jim-p
								$altnames_tmp[] = "{$altname['type']}:" . cert_escape_x509_chars($altname['value']);
449 a636256c jim-p
							}
450 2f65de89 jim-p
						}
451 a636256c jim-p
					}
452
					if (!empty($altnames_tmp)) {
453 2f65de89 jim-p
						$dn['subjectAltName'] = implode(",", $altnames_tmp);
454
					}
455 bf9d50e8 Stephen Beaver
456
					if (!cert_create($cert, $pconfig['caref'], $pconfig['keylen'], $pconfig['lifetime'], $dn, $pconfig['type'], $pconfig['digest_alg'])) {
457 5ce9bcf5 jim-p
						$input_errors = array();
458 56b1ed39 Phil Davis
						while ($ssl_err = openssl_error_string()) {
459 5ce9bcf5 jim-p
							if (strpos($ssl_err, 'NCONF_get_string:no value') === false) {
460
								array_push($input_errors, "openssl library returns: " . $ssl_err);
461
							}
462 22b380aa Evgeny Yurchenko
						}
463
					}
464 ad9b5c67 jim-p
				}
465
466
				if ($pconfig['method'] == "external") {
467 80d50253 jim-p
					$dn = array('commonName' => cert_escape_x509_chars($pconfig['csr_dn_commonname']));
468
					if (!empty($pconfig['csr_dn_country'])) {
469
						$dn['countryName'] = $pconfig['csr_dn_country'];
470
					}
471
					if (!empty($pconfig['csr_dn_state'])) {
472
						$dn['stateOrProvinceName'] = cert_escape_x509_chars($pconfig['csr_dn_state']);
473
					}
474
					if (!empty($pconfig['csr_dn_city'])) {
475
						$dn['localityName'] = cert_escape_x509_chars($pconfig['csr_dn_city']);
476
					}
477
					if (!empty($pconfig['csr_dn_organization'])) {
478
						$dn['organizationName'] = cert_escape_x509_chars($pconfig['csr_dn_organization']);
479
					}
480 da0f70ed jim-p
					if (!empty($pconfig['csr_dn_organizationalunit'])) {
481 83d2b83a jim-p
						$dn['organizationalUnitName'] = cert_escape_x509_chars($pconfig['csr_dn_organizationalunit']);
482 da0f70ed jim-p
					}
483 282b6c66 jim-p
484 e562fca2 jim-p
					$altnames_tmp = array();
485
					$cn_altname = cert_add_altname_type($pconfig['csr_dn_commonname']);
486
					if (!empty($cn_altname)) {
487
						$altnames_tmp[] = $cn_altname;
488
					}
489 2f65de89 jim-p
					if (count($altnames)) {
490
						foreach ($altnames as $altname) {
491 282b6c66 jim-p
							// The CN is added as a SAN automatically, do not add it again.
492
							if ($altname['value'] != $pconfig['csr_dn_commonname']) {
493
								$altnames_tmp[] = "{$altname['type']}:" . cert_escape_x509_chars($altname['value']);
494
							}
495 2f65de89 jim-p
						}
496 282b6c66 jim-p
					}
497
					if (!empty($altnames_tmp)) {
498 2f65de89 jim-p
						$dn['subjectAltName'] = implode(",", $altnames_tmp);
499
					}
500 b29c322c Stephen Beaver
501 282b6c66 jim-p
					if (!csr_generate($cert, $pconfig['csr_keylen'], $dn, $pconfig['type'], $pconfig['csr_digest_alg'])) {
502 5ce9bcf5 jim-p
						$input_errors = array();
503 56b1ed39 Phil Davis
						while ($ssl_err = openssl_error_string()) {
504 5ce9bcf5 jim-p
							if (strpos($ssl_err, 'NCONF_get_string:no value') === false) {
505
								array_push($input_errors, "openssl library returns: " . $ssl_err);
506
							}
507 22b380aa Evgeny Yurchenko
						}
508
					}
509 ad9b5c67 jim-p
				}
510 2052d3e2 Steve Beaver
511 22b380aa Evgeny Yurchenko
				error_reporting($old_err_level);
512
513 56b1ed39 Phil Davis
				if (isset($id) && $a_cert[$id]) {
514 ad9b5c67 jim-p
					$a_cert[$id] = $cert;
515 56b1ed39 Phil Davis
				} else {
516 ad9b5c67 jim-p
					$a_cert[] = $cert;
517 56b1ed39 Phil Davis
				}
518 bf9d50e8 Stephen Beaver
519 56b1ed39 Phil Davis
				if (isset($a_user) && isset($userid)) {
520 ad9b5c67 jim-p
					$a_user[$userid]['cert'][] = $cert['refid'];
521 56b1ed39 Phil Davis
				}
522 64cc39d3 Matthew Grooms
			}
523
524 56b1ed39 Phil Davis
			if (!$input_errors) {
525 22b380aa Evgeny Yurchenko
				write_config();
526 56b1ed39 Phil Davis
			}
527 64cc39d3 Matthew Grooms
528 cc175f70 jim-p
			if ((isset($userid) && is_numeric($userid)) && !$input_errors) {
529 1a6769a6 Renato Botelho
				post_redirect("system_usermanager.php", array('act' => 'edit', 'userid' => $userid));
530
				exit;
531
			}
532 64cc39d3 Matthew Grooms
		}
533
	}
534
535 a37753d7 Vinicius Coque
	if ($_POST['save'] == gettext("Update")) {
536 64cc39d3 Matthew Grooms
		unset($input_errors);
537
		$pconfig = $_POST;
538
539
		/* input validation */
540 5293bfec jim-p
		$reqdfields = explode(" ", "descr cert");
541 76d49f20 Renato Botelho
		$reqdfieldsn = array(
542 78863416 Phil Davis
			gettext("Descriptive name"),
543
			gettext("Final Certificate data"));
544 64cc39d3 Matthew Grooms
545 1e9b4611 Renato Botelho
		do_input_validation($_POST, $reqdfields, $reqdfieldsn, $input_errors);
546 64cc39d3 Matthew Grooms
547 b741d2ef jim-p
		if (preg_match("/[\?\>\<\&\/\\\"\']/", $_POST['descr'])) {
548
			array_push($input_errors, "The field 'Descriptive Name' contains invalid characters.");
549
		}
550
551 a828210b yakatz
//		old way
552 64cc39d3 Matthew Grooms
		/* make sure this csr and certificate subjects match */
553 a828210b yakatz
//		$subj_csr = csr_get_subject($pconfig['csr'], false);
554
//		$subj_cert = cert_get_subject($pconfig['cert'], false);
555
//
556 56b1ed39 Phil Davis
//		if (!isset($_POST['ignoresubjectmismatch']) && !($_POST['ignoresubjectmismatch'] == "yes")) {
557
//			if (strcmp($subj_csr, $subj_cert)) {
558
//				$input_errors[] = sprintf(gettext("The certificate subject '%s' does not match the signing request subject."), $subj_cert);
559 a828210b yakatz
//				$subject_mismatch = true;
560
//			}
561
//		}
562 1746c5ce PiBa-NL
		$mod_csr = cert_get_publickey($pconfig['csr'], false, 'csr');
563
		$mod_cert = cert_get_publickey($pconfig['cert'], false);
564 b49f31d0 Sjon Hortensius
565 56b1ed39 Phil Davis
		if (strcmp($mod_csr, $mod_cert)) {
566 a828210b yakatz
			// simply: if the moduli don't match, then the private key and public key won't match
567 1746c5ce PiBa-NL
			$input_errors[] = sprintf(gettext("The certificate public key does not match the signing request public key."), $subj_cert);
568 a828210b yakatz
			$subject_mismatch = true;
569
		}
570 64cc39d3 Matthew Grooms
571
		/* save modifications */
572
		if (!$input_errors) {
573
574
			$cert = $a_cert[$id];
575
576 f2a86ca9 jim-p
			$cert['descr'] = $pconfig['descr'];
577 64cc39d3 Matthew Grooms
578
			csr_complete($cert, $pconfig['cert']);
579
580
			$a_cert[$id] = $cert;
581
582
			write_config();
583
584
			pfSenseHeader("system_certmanager.php");
585
		}
586
	}
587
}
588
589 56c6b1cb k-paulius
$pgtitle = array(gettext("System"), gettext("Certificate Manager"), gettext("Certificates"));
590 edcd7535 Phil Davis
$pglinks = array("", "system_camanager.php", "system_certmanager.php");
591 56c6b1cb k-paulius
592
if (($act == "new" || ($_POST['save'] == gettext("Save") && $input_errors)) || ($act == "csr" || ($_POST['save'] == gettext("Update") && $input_errors))) {
593
	$pgtitle[] = gettext('Edit');
594 edcd7535 Phil Davis
	$pglinks[] = "@self";
595 56c6b1cb k-paulius
}
596 64cc39d3 Matthew Grooms
include("head.inc");
597 b49f31d0 Sjon Hortensius
598 78863416 Phil Davis
if ($input_errors) {
599 b49f31d0 Sjon Hortensius
	print_input_errors($input_errors);
600 78863416 Phil Davis
}
601 0edcccc3 Daniel Seebald
602 78863416 Phil Davis
if ($savemsg) {
603 3f0efd58 Stephen Beaver
	print_info_box($savemsg, 'success');
604 78863416 Phil Davis
}
605 b49f31d0 Sjon Hortensius
606
$tab_array = array();
607
$tab_array[] = array(gettext("CAs"), false, "system_camanager.php");
608
$tab_array[] = array(gettext("Certificates"), true, "system_certmanager.php");
609
$tab_array[] = array(gettext("Certificate Revocation"), false, "system_crlmanager.php");
610
display_top_tabs($tab_array);
611
612
// Load valid country codes
613
$dn_cc = array();
614 78863416 Phil Davis
if (file_exists("/etc/ca_countries")) {
615 b49f31d0 Sjon Hortensius
	$dn_cc_file=file("/etc/ca_countries");
616 80d50253 jim-p
	$dn_cc[''] = gettext("None");
617 78863416 Phil Davis
	foreach ($dn_cc_file as $line) {
618 b8f22f61 Stephen Beaver
		if (preg_match('/^(\S*)\s(.*)$/', $line, $matches)) {
619
			$dn_cc[$matches[1]] = $matches[1];
620
		}
621
	}
622 b49f31d0 Sjon Hortensius
}
623
624 b29c322c Stephen Beaver
if ($act == "new" || (($_POST['save'] == gettext("Save")) && $input_errors)) {
625 b35250d9 NewEraCracker
	$form = new Form();
626
	$form->setAction('system_certmanager.php?act=edit');
627 b49f31d0 Sjon Hortensius
628 b35250d9 NewEraCracker
	if (isset($userid) && $a_user) {
629
		$form->addGlobal(new Form_Input(
630
			'userid',
631
			null,
632
			'hidden',
633
			$userid
634
		));
635
	}
636 b49f31d0 Sjon Hortensius
637 78863416 Phil Davis
	if (isset($id) && $a_cert[$id]) {
638 b49f31d0 Sjon Hortensius
		$form->addGlobal(new Form_Input(
639
			'id',
640
			null,
641
			'hidden',
642
			$id
643
		));
644 64cc39d3 Matthew Grooms
	}
645 b49f31d0 Sjon Hortensius
646 2052d3e2 Steve Beaver
	$section = new Form_Section('Add/Sign a New Certificate');
647 b35250d9 NewEraCracker
648
	if (!isset($id)) {
649
		$section->addInput(new Form_Select(
650
			'method',
651 153c3aa6 Phil Davis
			'*Method',
652 b35250d9 NewEraCracker
			$pconfig['method'],
653
			$cert_methods
654
		))->toggles();
655
	}
656
657 b49f31d0 Sjon Hortensius
	$section->addInput(new Form_Input(
658
		'descr',
659 153c3aa6 Phil Davis
		'*Descriptive name',
660 b49f31d0 Sjon Hortensius
		'text',
661 b35250d9 NewEraCracker
		($a_user && empty($pconfig['descr'])) ? $a_user[$userid]['name'] : $pconfig['descr']
662
	))->addClass('toggle-existing');
663 b49f31d0 Sjon Hortensius
664 b35250d9 NewEraCracker
	$form->add($section);
665 2052d3e2 Steve Beaver
666 d520da31 Steve Beaver
	// Return an array containing the IDs od all CAs
667 2052d3e2 Steve Beaver
	function list_cas() {
668
		global $a_ca;
669
		$allCas = array();
670
671
		foreach ($a_ca as $ca) {
672
			if ($ca['prv']) {
673 d520da31 Steve Beaver
				$allCas[$ca['refid']] = $ca['descr'];
674 2052d3e2 Steve Beaver
			}
675
		}
676
677
		return $allCas;
678
	}
679
680 d520da31 Steve Beaver
	// Return an array containing the IDs od all CSRs
681 2052d3e2 Steve Beaver
	function list_csrs() {
682
		global $config;
683
		$allCsrs = array();
684
685
		foreach ($config['cert'] as $cert) {
686
			if ($cert['csr']) {
687 d520da31 Steve Beaver
				$allCsrs[$cert['refid']] = $cert['descr'];
688 2052d3e2 Steve Beaver
			}
689
		}
690
691 d6107e1a Steve Beaver
		return ['new' => gettext('New CSR (Paste below)')] + $allCsrs;
692 2052d3e2 Steve Beaver
	}
693
694
	$section = new Form_Section('Sign CSR');
695
	$section->addClass('toggle-sign collapse');
696
697
	$section->AddInput(new Form_Select(
698
		'catosignwith',
699
		'*CA to sign with',
700
		$pconfig['catosignwith'],
701
		list_cas()
702
	));
703
704
	$section->AddInput(new Form_Select(
705
		'csrtosign',
706
		'*CSR to sign',
707
		isset($pconfig['csrtosign']) ? $pconfig['csrtosign'] : 'new',
708
		list_csrs()
709
	));
710
711
	$section->addInput(new Form_Textarea(
712
		'csrpaste',
713
		'CSR data',
714
		$pconfig['csrpaste']
715
	))->setHelp('Paste a Certificate Signing Request in X.509 PEM format here.');
716
717 55047259 Steve Beaver
	$section->addInput(new Form_Textarea(
718
		'keypaste',
719
		'Key data',
720
		$pconfig['keypaste']
721
	))->setHelp('Optionally paste a private key here. The key will be associated with the newly signed certificate in pfSense');
722
723 0c82b8c2 jim-p
	$section->addInput(new Form_Input(
724
		'csrsign_lifetime',
725
		'*Certificate Lifetime (days)',
726
		'number',
727 aec3a259 jim-p
		$pconfig['csrsign_lifetime'] ? $pconfig['csrsign_lifetime']:'3650'
728 0c82b8c2 jim-p
	));
729 aec3a259 jim-p
	$section->addInput(new Form_Select(
730
		'csrsign_digest_alg',
731
		'*Digest Algorithm',
732
		$pconfig['csrsign_digest_alg'],
733
		array_combine($openssl_digest_algs, $openssl_digest_algs)
734
	))->setHelp('NOTE: It is recommended to use an algorithm stronger than '.
735
		'SHA1 when possible');
736 0c82b8c2 jim-p
737 2052d3e2 Steve Beaver
	$form->add($section);
738
739 b35250d9 NewEraCracker
	$section = new Form_Section('Import Certificate');
740
	$section->addClass('toggle-import collapse');
741 b49f31d0 Sjon Hortensius
742
	$section->addInput(new Form_Textarea(
743
		'cert',
744 153c3aa6 Phil Davis
		'*Certificate data',
745 78863416 Phil Davis
		$pconfig['cert']
746 b35250d9 NewEraCracker
	))->setHelp('Paste a certificate in X.509 PEM format here.');
747
748
	$section->addInput(new Form_Textarea(
749
		'key',
750 153c3aa6 Phil Davis
		'*Private key data',
751 b35250d9 NewEraCracker
		$pconfig['key']
752
	))->setHelp('Paste a private key in X.509 PEM format here.');
753 b49f31d0 Sjon Hortensius
754
	$form->add($section);
755 b35250d9 NewEraCracker
	$section = new Form_Section('Internal Certificate');
756
	$section->addClass('toggle-internal collapse');
757
758
	if (!$internal_ca_count) {
759
		$section->addInput(new Form_StaticText(
760 153c3aa6 Phil Davis
			'*Certificate authority',
761 781d9ce4 Phil Davis
			gettext('No internal Certificate Authorities have been defined. ') .
762
			gettext('An internal CA must be defined in order to create an internal certificate. ') .
763
			sprintf(gettext('%1$sCreate%2$s an internal CA.'), '<a href="system_camanager.php?act=new&amp;method=internal"> ', '</a>')
764 b35250d9 NewEraCracker
		));
765
	} else {
766
		$allCas = array();
767
		foreach ($a_ca as $ca) {
768
			if (!$ca['prv']) {
769
				continue;
770
			}
771 b49f31d0 Sjon Hortensius
772 b35250d9 NewEraCracker
			$allCas[ $ca['refid'] ] = $ca['descr'];
773
		}
774 64cc39d3 Matthew Grooms
775 b35250d9 NewEraCracker
		$section->addInput(new Form_Select(
776
			'caref',
777 153c3aa6 Phil Davis
			'*Certificate authority',
778 b35250d9 NewEraCracker
			$pconfig['caref'],
779
			$allCas
780
		));
781
	}
782 64cc39d3 Matthew Grooms
783 b35250d9 NewEraCracker
	$section->addInput(new Form_Select(
784
		'keylen',
785 153c3aa6 Phil Davis
		'*Key length',
786 b35250d9 NewEraCracker
		$pconfig['keylen'],
787
		array_combine($cert_keylens, $cert_keylens)
788 b49f31d0 Sjon Hortensius
	));
789 64cc39d3 Matthew Grooms
790 b35250d9 NewEraCracker
	$section->addInput(new Form_Select(
791
		'digest_alg',
792 153c3aa6 Phil Davis
		'*Digest Algorithm',
793 b35250d9 NewEraCracker
		$pconfig['digest_alg'],
794
		array_combine($openssl_digest_algs, $openssl_digest_algs)
795
	))->setHelp('NOTE: It is recommended to use an algorithm stronger than '.
796
		'SHA1 when possible.');
797 b49f31d0 Sjon Hortensius
798 b35250d9 NewEraCracker
	$section->addInput(new Form_Input(
799
		'lifetime',
800 153c3aa6 Phil Davis
		'*Lifetime (days)',
801 b35250d9 NewEraCracker
		'number',
802
		$pconfig['lifetime']
803
	));
804 b49f31d0 Sjon Hortensius
805 26e3967a jim-p
	$section->addInput(new Form_Input(
806
		'dn_commonname',
807
		'*Common Name',
808
		'text',
809
		$pconfig['dn_commonname'],
810
		['placeholder' => 'e.g. www.example.com']
811
	));
812
813
	$section->addInput(new Form_StaticText(
814
		null,
815
		gettext('The following certificate subject components are optional and may be left blank.')
816
	));
817
818 b49f31d0 Sjon Hortensius
	$section->addInput(new Form_Select(
819 b35250d9 NewEraCracker
		'dn_country',
820 80d50253 jim-p
		'Country Code',
821 b35250d9 NewEraCracker
		$pconfig['dn_country'],
822
		$dn_cc
823 b49f31d0 Sjon Hortensius
	));
824
825 b35250d9 NewEraCracker
	$section->addInput(new Form_Input(
826
		'dn_state',
827 80d50253 jim-p
		'State or Province',
828 b35250d9 NewEraCracker
		'text',
829
		$pconfig['dn_state'],
830
		['placeholder' => 'e.g. Texas']
831 b49f31d0 Sjon Hortensius
	));
832
833 b35250d9 NewEraCracker
	$section->addInput(new Form_Input(
834
		'dn_city',
835 80d50253 jim-p
		'City',
836 b35250d9 NewEraCracker
		'text',
837
		$pconfig['dn_city'],
838
		['placeholder' => 'e.g. Austin']
839
	));
840
841
	$section->addInput(new Form_Input(
842
		'dn_organization',
843 80d50253 jim-p
		'Organization',
844 b35250d9 NewEraCracker
		'text',
845
		$pconfig['dn_organization'],
846 da0f70ed jim-p
		['placeholder' => 'e.g. My Company Inc']
847
	));
848
849
	$section->addInput(new Form_Input(
850
		'dn_organizationalunit',
851
		'Organizational Unit',
852
		'text',
853
		$pconfig['dn_organizationalunit'],
854
		['placeholder' => 'e.g. My Department Name (optional)']
855 b35250d9 NewEraCracker
	));
856
857
	$form->add($section);
858
	$section = new Form_Section('External Signing Request');
859
	$section->addClass('toggle-external collapse');
860
861 b49f31d0 Sjon Hortensius
	$section->addInput(new Form_Select(
862 b35250d9 NewEraCracker
		'csr_keylen',
863 153c3aa6 Phil Davis
		'*Key length',
864 b35250d9 NewEraCracker
		$pconfig['csr_keylen'],
865
		array_combine($cert_keylens, $cert_keylens)
866 b49f31d0 Sjon Hortensius
	));
867 64cc39d3 Matthew Grooms
868 b35250d9 NewEraCracker
	$section->addInput(new Form_Select(
869
		'csr_digest_alg',
870 153c3aa6 Phil Davis
		'*Digest Algorithm',
871 b35250d9 NewEraCracker
		$pconfig['csr_digest_alg'],
872
		array_combine($openssl_digest_algs, $openssl_digest_algs)
873
	))->setHelp('NOTE: It is recommended to use an algorithm stronger than '.
874
		'SHA1 when possible');
875 b49f31d0 Sjon Hortensius
876 26e3967a jim-p
	$section->addInput(new Form_Input(
877
		'csr_dn_commonname',
878
		'*Common Name',
879
		'text',
880
		$pconfig['csr_dn_commonname'],
881
		['placeholder' => 'e.g. internal-ca']
882
	));
883
884
	$section->addInput(new Form_StaticText(
885
		null,
886
		gettext('The following certificate subject components are optional and may be left blank.')
887
	));
888
889 b35250d9 NewEraCracker
	$section->addInput(new Form_Select(
890
		'csr_dn_country',
891 80d50253 jim-p
		'Country Code',
892 b35250d9 NewEraCracker
		$pconfig['csr_dn_country'],
893
		$dn_cc
894
	));
895 bf9d50e8 Stephen Beaver
896 b35250d9 NewEraCracker
	$section->addInput(new Form_Input(
897
		'csr_dn_state',
898 80d50253 jim-p
		'State or Province',
899 b35250d9 NewEraCracker
		'text',
900
		$pconfig['csr_dn_state'],
901
		['placeholder' => 'e.g. Texas']
902
	));
903 bf9d50e8 Stephen Beaver
904 b35250d9 NewEraCracker
	$section->addInput(new Form_Input(
905
		'csr_dn_city',
906 80d50253 jim-p
		'City',
907 b35250d9 NewEraCracker
		'text',
908
		$pconfig['csr_dn_city'],
909
		['placeholder' => 'e.g. Austin']
910
	));
911 bf9d50e8 Stephen Beaver
912 b35250d9 NewEraCracker
	$section->addInput(new Form_Input(
913
		'csr_dn_organization',
914 80d50253 jim-p
		'Organization',
915 b35250d9 NewEraCracker
		'text',
916
		$pconfig['csr_dn_organization'],
917 da0f70ed jim-p
		['placeholder' => 'e.g. My Company Inc']
918
	));
919
920
	$section->addInput(new Form_Input(
921
		'csr_dn_organizationalunit',
922
		'Organizational Unit',
923
		'text',
924
		$pconfig['csr_dn_organizationalunit'],
925
		['placeholder' => 'e.g. My Department Name (optional)']
926 b35250d9 NewEraCracker
	));
927 b49f31d0 Sjon Hortensius
928 0c82b8c2 jim-p
	$form->add($section);
929
	$section = new Form_Section('Choose an Existing Certificate');
930
	$section->addClass('toggle-existing collapse');
931
932
	$existCerts = array();
933
934
	foreach ($config['cert'] as $cert)	{
935
		if (is_array($config['system']['user'][$userid]['cert'])) { // Could be MIA!
936
			if (isset($userid) && in_array($cert['refid'], $config['system']['user'][$userid]['cert'])) {
937
				continue;
938
			}
939
		}
940
941
		$ca = lookup_ca($cert['caref']);
942
		if ($ca) {
943
			$cert['descr'] .= " (CA: {$ca['descr']})";
944
		}
945
946
		if (cert_in_use($cert['refid'])) {
947
			$cert['descr'] .= " (In Use)";
948
		}
949
		if (is_cert_revoked($cert)) {
950
			$cert['descr'] .= " (Revoked)";
951
		}
952
953
		$existCerts[ $cert['refid'] ] = $cert['descr'];
954
	}
955
956
	$section->addInput(new Form_Select(
957
		'certref',
958
		'*Existing Certificates',
959
		$pconfig['certref'],
960
		$existCerts
961
	));
962
963
	$form->add($section);
964
965
	$section = new Form_Section('Certificate Attributes');
966
	$section->addClass('toggle-external toggle-internal toggle-sign collapse');
967
968
	$section->addInput(new Form_StaticText(
969
		gettext('Attribute Notes'),
970
		'<span class="help-block">'.
971
		gettext('The following attributes are added to certificates and ' .
972
		'requests when they are created or signed. These attributes behave ' .
973
		'differently depending on the selected mode.') .
974
		'<br/><br/>' .
975
		'<span class="toggle-internal collapse">' . gettext('For Internal Certificates, these attributes are added directly to the certificate as shown.') . '</span>' .
976
		'<span class="toggle-external collapse">' .
977
		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. ') .
978
		'<br/><br/>' .
979
		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>' .
980
		'<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>' .
981
		'</span>'
982
	));
983
984
	$section->addInput(new Form_Select(
985
		'type',
986
		'*Certificate Type',
987
		$pconfig['type'],
988
		$cert_types
989
	))->setHelp('Add type-specific usage attributes to the signed certificate.' .
990
		' Used for placing usage restrictions on, or granting abilities to, ' .
991
		'the signed certificate.');
992
993 282b6c66 jim-p
	if (empty($pconfig['altnames']['item'])) {
994
		$pconfig['altnames']['item'] = array(
995
			array('type' => null, 'value' => null)
996
		);
997
	}
998
999
	$counter = 0;
1000
	$numrows = count($pconfig['altnames']['item']) - 1;
1001
1002
	foreach ($pconfig['altnames']['item'] as $item) {
1003
1004
		$group = new Form_Group($counter == 0 ? 'Alternative Names':'');
1005
1006
		$group->add(new Form_Select(
1007
			'altname_type' . $counter,
1008
			'Type',
1009
			$item['type'],
1010
			$cert_altname_types
1011
		))->setHelp(($counter == $numrows) ? 'Type':null);
1012
1013
		$group->add(new Form_Input(
1014
			'altname_value' . $counter,
1015
			null,
1016
			'text',
1017
			$item['value']
1018
		))->setHelp(($counter == $numrows) ? 'Value':null);
1019
1020
		$group->add(new Form_Button(
1021
			'deleterow' . $counter,
1022
			'Delete',
1023
			null,
1024
			'fa-trash'
1025
		))->addClass('btn-warning');
1026
1027
		$group->addClass('repeatable');
1028
1029 0c82b8c2 jim-p
		$group->setHelp('Enter additional identifiers for the certificate ' .
1030
			'in this list. The Common Name field is automatically ' .
1031
			'added to the certificate as an Alternative Name. ' .
1032
			'The signing CA may ignore or change these values.');
1033 282b6c66 jim-p
1034
		$section->add($group);
1035
1036
		$counter++;
1037
	}
1038
1039
	$section->addInput(new Form_Button(
1040
		'addrow',
1041
		'Add',
1042
		null,
1043
		'fa-plus'
1044
	))->addClass('btn-success');
1045
1046 b35250d9 NewEraCracker
	$form->add($section);
1047 b49f31d0 Sjon Hortensius
1048
1049 b35250d9 NewEraCracker
	print $form;
1050 64cc39d3 Matthew Grooms
1051 b29c322c Stephen Beaver
} else if ($act == "csr" || (($_POST['save'] == gettext("Update")) && $input_errors)) {
1052 8f58b51b jim-p
	$form = new Form(false);
1053 308f0665 NewEraCracker
	$form->setAction('system_certmanager.php?act=csr');
1054 b29c322c Stephen Beaver
1055 5f88f964 k-paulius
	$section = new Form_Section("Complete Signing Request for " . $pconfig['descr']);
1056 b29c322c Stephen Beaver
1057 ba5c55e9 Stephen Beaver
	$section->addInput(new Form_Input(
1058
		'descr',
1059 153c3aa6 Phil Davis
		'*Descriptive name',
1060 ba5c55e9 Stephen Beaver
		'text',
1061
		$pconfig['descr']
1062
	));
1063
1064 b29c322c Stephen Beaver
	$section->addInput(new Form_Textarea(
1065
		'csr',
1066
		'Signing request data',
1067
		$pconfig['csr']
1068
	))->setReadonly()
1069 af28e231 Stephen Beaver
	  ->setWidth(7)
1070 813c6673 NOYB
	  ->setHelp('Copy the certificate signing data from here and forward it to a certificate authority for signing.');
1071 b29c322c Stephen Beaver
1072
	$section->addInput(new Form_Textarea(
1073
		'cert',
1074 153c3aa6 Phil Davis
		'*Final certificate data',
1075 b29c322c Stephen Beaver
		$pconfig['cert']
1076 af28e231 Stephen Beaver
	))->setWidth(7)
1077 813c6673 NOYB
	  ->setHelp('Paste the certificate received from the certificate authority here.');
1078 b29c322c Stephen Beaver
1079
	 if (isset($id) && $a_cert[$id]) {
1080
		 $section->addInput(new Form_Input(
1081
			'id',
1082
			null,
1083
			'hidden',
1084
			$id
1085
		 ));
1086
1087
		 $section->addInput(new Form_Input(
1088
			'act',
1089
			null,
1090
			'hidden',
1091
			'csr'
1092
		 ));
1093
	 }
1094
1095
	$form->add($section);
1096 8f58b51b jim-p
1097
	$form->addGlobal(new Form_Button(
1098 141d8913 jim-p
		'save',
1099 faab522f Renato Botelho
		'Update',
1100 8f58b51b jim-p
		null,
1101
		'fa-save'
1102
	))->addClass('btn-primary');
1103
1104 b29c322c Stephen Beaver
	print($form);
1105
} else {
1106
?>
1107 060ed238 Stephen Beaver
<div class="panel panel-default">
1108
	<div class="panel-heading"><h2 class="panel-title"><?=gettext('Certificates')?></h2></div>
1109
	<div class="panel-body">
1110
		<div class="table-responsive">
1111
		<table class="table table-striped table-hover">
1112
			<thead>
1113
				<tr>
1114
					<th><?=gettext("Name")?></th>
1115
					<th><?=gettext("Issuer")?></th>
1116
					<th><?=gettext("Distinguished Name")?></th>
1117
					<th><?=gettext("In Use")?></th>
1118 4db1f211 Stephen Beaver
1119 060ed238 Stephen Beaver
					<th class="col-sm-2"><?=gettext("Actions")?></th>
1120
				</tr>
1121
			</thead>
1122
			<tbody>
1123 b29c322c Stephen Beaver
<?php
1124 4db1f211 Stephen Beaver
1125
$pluginparams = array();
1126
$pluginparams['type'] = 'certificates';
1127
$pluginparams['event'] = 'used_certificates';
1128
$certificates_used_by_packages = pkg_call_plugins('plugin_certificates', $pluginparams);
1129
$i = 0;
1130 78863416 Phil Davis
foreach ($a_cert as $i => $cert):
1131 b29c322c Stephen Beaver
	$name = htmlspecialchars($cert['descr']);
1132 00d5594c jim-p
	$sans = array();
1133 b29c322c Stephen Beaver
	if ($cert['crt']) {
1134
		$subj = cert_get_subject($cert['crt']);
1135
		$issuer = cert_get_issuer($cert['crt']);
1136
		$purpose = cert_get_purpose($cert['crt']);
1137 4906f4ee jim-p
		$sans = cert_get_sans($cert['crt']);
1138 b29c322c Stephen Beaver
		list($startdate, $enddate) = cert_get_dates($cert['crt']);
1139
1140 78863416 Phil Davis
		if ($subj == $issuer) {
1141 b29c322c Stephen Beaver
			$caname = '<i>'. gettext("self-signed") .'</i>';
1142 78863416 Phil Davis
		} else {
1143 b29c322c Stephen Beaver
			$caname = '<i>'. gettext("external").'</i>';
1144 78863416 Phil Davis
		}
1145 b29c322c Stephen Beaver
1146 83d2b83a jim-p
		$subj = htmlspecialchars(cert_escape_x509_chars($subj, true));
1147 1048585a PiBa-NL
	} else {
1148
		$subj = "";
1149
		$issuer = "";
1150
		$purpose = "";
1151
		$startdate = "";
1152
		$enddate = "";
1153
		$caname = "<em>" . gettext("private key only") . "</em>";
1154 b29c322c Stephen Beaver
	}
1155
1156
	if ($cert['csr']) {
1157 83d2b83a jim-p
		$subj = htmlspecialchars(cert_escape_x509_chars(csr_get_subject($cert['csr']), true));
1158 4906f4ee jim-p
		$sans = cert_get_sans($cert['crt']);
1159 b29c322c Stephen Beaver
		$caname = "<em>" . gettext("external - signature pending") . "</em>";
1160
	}
1161
1162
	$ca = lookup_ca($cert['caref']);
1163 78863416 Phil Davis
	if ($ca) {
1164 b29c322c Stephen Beaver
		$caname = $ca['descr'];
1165 78863416 Phil Davis
	}
1166 b29c322c Stephen Beaver
?>
1167 060ed238 Stephen Beaver
				<tr>
1168
					<td>
1169
						<?=$name?><br />
1170
						<?php if ($cert['type']): ?>
1171
							<i><?=$cert_types[$cert['type']]?></i><br />
1172
						<?php endif?>
1173
						<?php if (is_array($purpose)): ?>
1174 4906f4ee jim-p
							CA: <b><?=$purpose['ca']?></b><br/>
1175
							<?=gettext("Server")?>: <b><?=$purpose['server']?></b><br/>
1176 060ed238 Stephen Beaver
						<?php endif?>
1177
					</td>
1178
					<td><?=$caname?></td>
1179
					<td>
1180
						<?=$subj?>
1181 4906f4ee jim-p
						<?php
1182
						$certextinfo = "";
1183 aec3a259 jim-p
						$certserial = cert_get_serial($cert['crt']);
1184
						if (!empty($certserial)) {
1185
							$certextinfo .= '<b>' . gettext("Serial: ") . '</b> ';
1186
							$certextinfo .= htmlspecialchars(cert_escape_x509_chars($certserial, true));
1187
							$certextinfo .= '<br/>';
1188
						}
1189
						$certsig = cert_get_sigtype($cert['crt']);
1190
						if (is_array($certsig) && !empty($certsig) && !empty($certsig['shortname'])) {
1191
							$certextinfo .= '<b>' . gettext("Signature Digest: ") . '</b> ';
1192
							$certextinfo .= htmlspecialchars(cert_escape_x509_chars($certsig['shortname'], true));
1193
							$certextinfo .= '<br/>';
1194
						}
1195 4906f4ee jim-p
						if (is_array($sans) && !empty($sans)) {
1196
							$certextinfo .= '<b>' . gettext("SAN: ") . '</b> ';
1197 2e1809dd jim-p
							$certextinfo .= htmlspecialchars(implode(', ', cert_escape_x509_chars($sans, true)));
1198 4906f4ee jim-p
							$certextinfo .= '<br/>';
1199
						}
1200
						if (is_array($purpose) && !empty($purpose['ku'])) {
1201
							$certextinfo .= '<b>' . gettext("KU: ") . '</b> ';
1202
							$certextinfo .= htmlspecialchars(implode(', ', $purpose['ku']));
1203
							$certextinfo .= '<br/>';
1204
						}
1205
						if (is_array($purpose) && !empty($purpose['eku'])) {
1206
							$certextinfo .= '<b>' . gettext("EKU: ") . '</b> ';
1207
							$certextinfo .= htmlspecialchars(implode(', ', $purpose['eku']));
1208 00e54150 jim-p
							$certextinfo .= '<br/>';
1209
						}
1210 0276ff2e Peter Berbec
						if (cert_get_ocspstaple($cert['crt'])) {
1211
							$certextinfo .= '<b>' . gettext("OCSP: ") . '</b> ';
1212
							$certextinfo .= gettext("Must Staple");
1213 1e238af4 Peter Berbec
						}
1214 4906f4ee jim-p
						?>
1215
						<?php if (!empty($certextinfo)): ?>
1216
							<div class="infoblock">
1217
							<? print_info_box($certextinfo, 'info', false); ?>
1218
							</div>
1219
						<?php endif?>
1220
1221
						<?php if (!empty($startdate) || !empty($enddate)): ?>
1222 b090c741 jim-p
						<br />
1223 060ed238 Stephen Beaver
						<small>
1224
							<?=gettext("Valid From")?>: <b><?=$startdate ?></b><br /><?=gettext("Valid Until")?>: <b><?=$enddate ?></b>
1225
						</small>
1226
						<?php endif?>
1227
					</td>
1228
					<td>
1229
						<?php if (is_cert_revoked($cert)): ?>
1230 762faef5 Phil Davis
							<i><?=gettext("Revoked")?></i>
1231 060ed238 Stephen Beaver
						<?php endif?>
1232
						<?php if (is_webgui_cert($cert['refid'])): ?>
1233 762faef5 Phil Davis
							<?=gettext("webConfigurator")?>
1234 060ed238 Stephen Beaver
						<?php endif?>
1235
						<?php if (is_user_cert($cert['refid'])): ?>
1236 762faef5 Phil Davis
							<?=gettext("User Cert")?>
1237 060ed238 Stephen Beaver
						<?php endif?>
1238
						<?php if (is_openvpn_server_cert($cert['refid'])): ?>
1239 762faef5 Phil Davis
							<?=gettext("OpenVPN Server")?>
1240 060ed238 Stephen Beaver
						<?php endif?>
1241
						<?php if (is_openvpn_client_cert($cert['refid'])): ?>
1242 762faef5 Phil Davis
							<?=gettext("OpenVPN Client")?>
1243 060ed238 Stephen Beaver
						<?php endif?>
1244
						<?php if (is_ipsec_cert($cert['refid'])): ?>
1245 762faef5 Phil Davis
							<?=gettext("IPsec Tunnel")?>
1246 060ed238 Stephen Beaver
						<?php endif?>
1247
						<?php if (is_captiveportal_cert($cert['refid'])): ?>
1248 762faef5 Phil Davis
							<?=gettext("Captive Portal")?>
1249 060ed238 Stephen Beaver
						<?php endif?>
1250 3bde5cdd PiBa-NL
						<?php echo cert_usedby_description($cert['refid'], $certificates_used_by_packages); ?>
1251 060ed238 Stephen Beaver
					</td>
1252
					<td>
1253
						<?php if (!$cert['csr']): ?>
1254 4611e283 Steve Beaver
							<a href="system_certmanager.php?act=exp&amp;id=<?=$i?>" class="fa fa-certificate" title="<?=gettext("Export Certificate")?>"></a>
1255 4594038a Steve Beaver
							<?php if ($cert['prv']): ?>
1256
								<a href="system_certmanager.php?act=key&amp;id=<?=$i?>" class="fa fa-key" title="<?=gettext("Export Key")?>"></a>
1257
							<?php endif?>
1258 4611e283 Steve Beaver
							<a href="system_certmanager.php?act=p12&amp;id=<?=$i?>" class="fa fa-archive" title="<?=gettext("Export P12")?>"></a>
1259 060ed238 Stephen Beaver
						<?php else: ?>
1260 4611e283 Steve Beaver
							<a href="system_certmanager.php?act=csr&amp;id=<?=$i?>" class="fa fa-pencil" title="<?=gettext("Update CSR")?>"></a>
1261
							<a href="system_certmanager.php?act=req&amp;id=<?=$i?>" class="fa fa-sign-in" title="<?=gettext("Export Request")?>"></a>
1262
							<a href="system_certmanager.php?act=key&amp;id=<?=$i?>" class="fa fa-key" title="<?=gettext("Export Key")?>"></a>
1263 060ed238 Stephen Beaver
						<?php endif?>
1264
						<?php if (!cert_in_use($cert['refid'])): ?>
1265 fe914124 Steve Beaver
							<a href="system_certmanager.php?act=del&amp;id=<?=$i?>" class="fa fa-trash" title="<?=gettext("Delete Certificate")?>" usepost></a>
1266 060ed238 Stephen Beaver
						<?php endif?>
1267
					</td>
1268
				</tr>
1269 4db1f211 Stephen Beaver
<?php
1270 e8afd822 Steve Beaver
	$i++;
1271 4db1f211 Stephen Beaver
	endforeach; ?>
1272 060ed238 Stephen Beaver
			</tbody>
1273
		</table>
1274
		</div>
1275
	</div>
1276 b29c322c Stephen Beaver
</div>
1277
1278
<nav class="action-buttons">
1279 4611e283 Steve Beaver
	<a href="?act=new" class="btn btn-success btn-sm">
1280 b29c322c Stephen Beaver
		<i class="fa fa-plus icon-embed-btn"></i>
1281 2052d3e2 Steve Beaver
		<?=gettext("Add/Sign")?>
1282 b29c322c Stephen Beaver
	</a>
1283
</nav>
1284 e9258698 NewEraCracker
<?php
1285 b29c322c Stephen Beaver
	include("foot.inc");
1286
	exit;
1287
}
1288
1289
1290 51583438 Stephen Beaver
?>
1291 8fd9052f Colin Fleming
<script type="text/javascript">
1292 51583438 Stephen Beaver
//<![CDATA[
1293 78863416 Phil Davis
events.push(function() {
1294 bf9d50e8 Stephen Beaver
1295 51583438 Stephen Beaver
<?php if ($internal_ca_count): ?>
1296
	function internalca_change() {
1297
1298
		caref = $('#caref').val();
1299
1300
		switch (caref) {
1301
<?php
1302
			foreach ($a_ca as $ca):
1303
				if (!$ca['prv']) {
1304
					continue;
1305
				}
1306
1307 1ec79365 jim-p
				$subject = cert_get_subject_hash($ca['crt']);
1308 51583438 Stephen Beaver
?>
1309
				case "<?=$ca['refid'];?>":
1310 1ec79365 jim-p
					$('#dn_country').val(<?=json_encode(cert_escape_x509_chars($subject['C'], true));?>);
1311
					$('#dn_state').val(<?=json_encode(cert_escape_x509_chars($subject['ST'], true));?>);
1312
					$('#dn_city').val(<?=json_encode(cert_escape_x509_chars($subject['L'], true));?>);
1313
					$('#dn_organization').val(<?=json_encode(cert_escape_x509_chars($subject['O'], true));?>);
1314
					$('#dn_organizationalunit').val(<?=json_encode(cert_escape_x509_chars($subject['OU'], 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');