Project

General

Profile

Download (26 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
	system_certmanager.php
4

    
5
	Copyright (C) 2008 Shrew Soft Inc.
6
	Copyright (C) 2013-2015 Electric Sheep Fencing, LP
7
	All rights reserved.
8

    
9
	Redistribution and use in source and binary forms, with or without
10
	modification, are permitted provided that the following conditions are met:
11

    
12
	1. Redistributions of source code must retain the above copyright notice,
13
	   this list of conditions and the following disclaimer.
14

    
15
	2. Redistributions in binary form must reproduce the above copyright
16
	   notice, this list of conditions and the following disclaimer in the
17
	   documentation and/or other materials provided with the distribution.
18

    
19
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
20
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
21
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
23
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28
	POSSIBILITY OF SUCH DAMAGE.
29
*/
30
/*
31
	pfSense_MODULE:	certificate_manager
32
*/
33

    
34
##|+PRIV
35
##|*IDENT=page-system-certmanager
36
##|*NAME=System: Certificate Manager
37
##|*DESCR=Allow access to the 'System: Certificate Manager' page.
38
##|*MATCH=system_certmanager.php*
39
##|-PRIV
40

    
41
require("guiconfig.inc");
42
require_once("certs.inc");
43

    
44
$cert_methods = array(
45
	"import" => gettext("Import an existing Certificate"),
46
	"internal" => gettext("Create an internal Certificate"),
47
	"external" => gettext("Create a Certificate Signing Request"),
48
);
49

    
50
$cert_keylens = array("512", "1024", "2048", "4096");
51
$cert_types = array(
52
	"ca" => "Certificate Authority",
53
	"server" => "Server Certificate",
54
	"user" => "User Certificate");
55

    
56
$altname_types = array("DNS", "IP", "email", "URI");
57
$openssl_digest_algs = array("sha1", "sha224", "sha256", "sha384", "sha512");
58

    
59
$pgtitle = array(gettext("System"), gettext("Certificate Manager"));
60

    
61
if (is_numericint($_GET['userid'])) {
62
	$userid = $_GET['userid'];
63
}
64
if (isset($_POST['userid']) && is_numericint($_POST['userid'])) {
65
	$userid = $_POST['userid'];
66
}
67

    
68
if (isset($userid)) {
69
	$cert_methods["existing"] = gettext("Choose an existing certificate");
70
	if (!is_array($config['system']['user'])) {
71
		$config['system']['user'] = array();
72
	}
73
	$a_user =& $config['system']['user'];
74
}
75

    
76
if (is_numericint($_GET['id'])) {
77
	$id = $_GET['id'];
78
}
79
if (isset($_POST['id']) && is_numericint($_POST['id'])) {
80
	$id = $_POST['id'];
81
}
82

    
83
if (!is_array($config['ca'])) {
84
	$config['ca'] = array();
85
}
86

    
87
$a_ca =& $config['ca'];
88

    
89
if (!is_array($config['cert'])) {
90
	$config['cert'] = array();
91
}
92

    
93
$a_cert =& $config['cert'];
94

    
95
$internal_ca_count = 0;
96
foreach ($a_ca as $ca) {
97
	if ($ca['prv']) {
98
		$internal_ca_count++;
99
	}
100
}
101

    
102
$act = $_GET['act'];
103
if ($_POST['act']) {
104
	$act = $_POST['act'];
105
}
106

    
107
if ($act == "del") {
108

    
109
	if (!isset($a_cert[$id])) {
110
		pfSenseHeader("system_certmanager.php");
111
		exit;
112
	}
113

    
114
	unset($a_cert[$id]);
115
	write_config();
116
	$savemsg = sprintf(gettext("Certificate %s successfully deleted"), htmlspecialchars($a_cert[$id]['descr'])) . "<br />";
117
	pfSenseHeader("system_certmanager.php");
118
	exit;
119
}
120

    
121
if ($act == "new") {
122
	$pconfig['method'] = $_GET['method'];
123
	$pconfig['keylen'] = "2048";
124
	$pconfig['digest_alg'] = "sha256";
125
	$pconfig['csr_keylen'] = "2048";
126
	$pconfig['csr_digest_alg'] = "sha256";
127
	$pconfig['type'] = "user";
128
	$pconfig['lifetime'] = "3650";
129
}
130

    
131
if ($act == "exp") {
132

    
133
	if (!$a_cert[$id]) {
134
		pfSenseHeader("system_certmanager.php");
135
		exit;
136
	}
137

    
138
	$exp_name = urlencode("{$a_cert[$id]['descr']}.crt");
139
	$exp_data = base64_decode($a_cert[$id]['crt']);
140
	$exp_size = strlen($exp_data);
141

    
142
	header("Content-Type: application/octet-stream");
143
	header("Content-Disposition: attachment; filename={$exp_name}");
144
	header("Content-Length: $exp_size");
145
	echo $exp_data;
146
	exit;
147
}
148

    
149
if ($act == "key") {
150

    
151
	if (!$a_cert[$id]) {
152
		pfSenseHeader("system_certmanager.php");
153
		exit;
154
	}
155

    
156
	$exp_name = urlencode("{$a_cert[$id]['descr']}.key");
157
	$exp_data = base64_decode($a_cert[$id]['prv']);
158
	$exp_size = strlen($exp_data);
159

    
160
	header("Content-Type: application/octet-stream");
161
	header("Content-Disposition: attachment; filename={$exp_name}");
162
	header("Content-Length: $exp_size");
163
	echo $exp_data;
164
	exit;
165
}
166

    
167
if ($act == "p12") {
168
	if (!$a_cert[$id]) {
169
		pfSenseHeader("system_certmanager.php");
170
		exit;
171
	}
172

    
173
	$exp_name = urlencode("{$a_cert[$id]['descr']}.p12");
174
	$args = array();
175
	$args['friendly_name'] = $a_cert[$id]['descr'];
176

    
177
	$ca = lookup_ca($a_cert[$id]['caref']);
178
	if ($ca) {
179
		$args['extracerts'] = openssl_x509_read(base64_decode($ca['crt']));
180
	}
181

    
182
	$res_crt = openssl_x509_read(base64_decode($a_cert[$id]['crt']));
183
	$res_key = openssl_pkey_get_private(array(0 => base64_decode($a_cert[$id]['prv']) , 1 => ""));
184

    
185
	$exp_data = "";
186
	openssl_pkcs12_export($res_crt, $exp_data, $res_key, null, $args);
187
	$exp_size = strlen($exp_data);
188

    
189
	header("Content-Type: application/octet-stream");
190
	header("Content-Disposition: attachment; filename={$exp_name}");
191
	header("Content-Length: $exp_size");
192
	echo $exp_data;
193
	exit;
194
}
195

    
196
if ($act == "csr") {
197

    
198
	if (!$a_cert[$id]) {
199
		pfSenseHeader("system_certmanager.php");
200
		exit;
201
	}
202

    
203
	$pconfig['descr'] = $a_cert[$id]['descr'];
204
	$pconfig['csr'] = base64_decode($a_cert[$id]['csr']);
205
}
206

    
207
if ($_POST) {
208
	if ($_POST['save'] == gettext("Save")) {
209
		$input_errors = array();
210
		$pconfig = $_POST;
211

    
212
		/* input validation */
213
		if ($pconfig['method'] == "import") {
214
			$reqdfields = explode(" ",
215
				"descr cert key");
216
			$reqdfieldsn = array(
217
				gettext("Descriptive name"),
218
				gettext("Certificate data"),
219
				gettext("Key data"));
220
			if ($_POST['cert'] && (!strstr($_POST['cert'], "BEGIN CERTIFICATE") || !strstr($_POST['cert'], "END CERTIFICATE"))) {
221
				$input_errors[] = gettext("This certificate does not appear to be valid.");
222
			}
223
		}
224

    
225
		if ($pconfig['method'] == "internal") {
226
			$reqdfields = explode(" ",
227
				"descr caref keylen type lifetime dn_country dn_state dn_city ".
228
				"dn_organization dn_email dn_commonname");
229
			$reqdfieldsn = array(
230
				gettext("Descriptive name"),
231
				gettext("Certificate authority"),
232
				gettext("Key length"),
233
				gettext("Certificate Type"),
234
				gettext("Lifetime"),
235
				gettext("Distinguished name Country Code"),
236
				gettext("Distinguished name State or Province"),
237
				gettext("Distinguished name City"),
238
				gettext("Distinguished name Organization"),
239
				gettext("Distinguished name Email Address"),
240
				gettext("Distinguished name Common Name"));
241
		}
242

    
243
		if ($pconfig['method'] == "external") {
244
			$reqdfields = explode(" ",
245
				"descr csr_keylen csr_dn_country csr_dn_state csr_dn_city ".
246
				"csr_dn_organization csr_dn_email csr_dn_commonname");
247
			$reqdfieldsn = array(
248
				gettext("Descriptive name"),
249
				gettext("Key length"),
250
				gettext("Distinguished name Country Code"),
251
				gettext("Distinguished name State or Province"),
252
				gettext("Distinguished name City"),
253
				gettext("Distinguished name Organization"),
254
				gettext("Distinguished name Email Address"),
255
				gettext("Distinguished name Common Name"));
256
		}
257

    
258
		if ($pconfig['method'] == "existing") {
259
			$reqdfields = array("certref");
260
			$reqdfieldsn = array(gettext("Existing Certificate Choice"));
261
		}
262

    
263
		$altnames = array();
264
		do_input_validation($_POST, $reqdfields, $reqdfieldsn, $input_errors);
265
		if ($pconfig['method'] != "import" && $pconfig['method'] != "existing") {
266
			/* subjectAltNames */
267
			foreach ($_POST['altname_value'] as $idx => $value) {
268
				if (empty($value))
269
					continue;
270

    
271
				$altnames[$idx] = array(
272
					'type' => $_POST['altname_type'][$idx],
273
					'value' => $value
274
				);
275
			}
276
			$pconfig['altnames']['item'] = $altnames;
277

    
278
			/* Input validation for subjectAltNames */
279
			foreach ($altnames as $idx => $altname) {
280
				switch ($altname['type']) {
281
					case "DNS":
282
						if (!is_hostname($altname['value'])) {
283
							array_push($input_errors, "DNS subjectAltName values must be valid hostnames or FQDNs");
284
						}
285
						break;
286
					case "IP":
287
						if (!is_ipaddr($altname['value'])) {
288
							array_push($input_errors, "IP subjectAltName values must be valid IP Addresses");
289
						}
290
						break;
291
					case "email":
292
						if (empty($altname['value'])) {
293
							array_push($input_errors, "You must provide an e-mail address for this type of subjectAltName");
294
						}
295
						if (preg_match("/[\!\#\$\%\^\(\)\~\?\>\<\&\/\\\,\"\']/", $altname['value'])) {
296
							array_push($input_errors, "The e-mail provided in a subjectAltName contains invalid characters.");
297
						}
298
						break;
299
					case "URI":
300
						/* Close enough? */
301
						if (!is_URL($altname['value'])) {
302
							$input_errors[] = "URI subjectAltName types must be a valid URI";
303
						}
304
						break;
305
					default:
306
						$input_errors[] = "Unrecognized subjectAltName type.";
307
				}
308
			}
309

    
310
			/* Make sure we do not have invalid characters in the fields for the certificate */
311

    
312
			if (preg_match("/[\?\>\<\&\/\\\"\']/", $_POST['descr'])) {
313
				array_push($input_errors, "The field 'Descriptive Name' contains invalid characters.");
314
			}
315

    
316
			for ($i = 0; $i < count($reqdfields); $i++) {
317
				if (preg_match('/email/', $reqdfields[$i])) { /* dn_email or csr_dn_name */
318
					if (preg_match("/[\!\#\$\%\^\(\)\~\?\>\<\&\/\\\,\"\']/", $_POST[$reqdfields[$i]])) {
319
						array_push($input_errors, "The field 'Distinguished name Email Address' contains invalid characters.");
320
					}
321
				} else if (preg_match('/commonname/', $reqdfields[$i])) { /* dn_commonname or csr_dn_commonname */
322
					if (preg_match("/[\!\@\#\$\%\^\(\)\~\?\>\<\&\/\\\,\"\']/", $_POST[$reqdfields[$i]])) {
323
						array_push($input_errors, "The field 'Distinguished name Common Name' contains invalid characters.");
324
					}
325
				} else if (($reqdfields[$i] != "descr") && preg_match("/[\!\@\#\$\%\^\(\)\~\?\>\<\&\/\\\,\.\"\']/", $_POST[$reqdfields[$i]])) {
326
					array_push($input_errors, "The field '" . $reqdfieldsn[$i] . "' contains invalid characters.");
327
				}
328
			}
329

    
330
			if (($pconfig['method'] != "external") && isset($_POST["keylen"]) && !in_array($_POST["keylen"], $cert_keylens)) {
331
				array_push($input_errors, gettext("Please select a valid Key Length."));
332
			}
333
			if (($pconfig['method'] != "external") && !in_array($_POST["digest_alg"], $openssl_digest_algs)) {
334
				array_push($input_errors, gettext("Please select a valid Digest Algorithm."));
335
			}
336

    
337
			if (($pconfig['method'] == "external") && isset($_POST["csr_keylen"]) && !in_array($_POST["csr_keylen"], $cert_keylens)) {
338
				array_push($input_errors, gettext("Please select a valid Key Length."));
339
			}
340
			if (($pconfig['method'] == "external") && !in_array($_POST["csr_digest_alg"], $openssl_digest_algs)) {
341
				array_push($input_errors, gettext("Please select a valid Digest Algorithm."));
342
			}
343
		}
344

    
345
		/* if this is an AJAX caller then handle via JSON */
346
		if (isAjax() && is_array($input_errors)) {
347
			input_errors2Ajax($input_errors);
348
			exit;
349
		}
350

    
351
		/* save modifications */
352
		if (!$input_errors) {
353

    
354
			if ($pconfig['method'] == "existing") {
355
				$cert = lookup_cert($pconfig['certref']);
356
				if ($cert && $a_user) {
357
					$a_user[$userid]['cert'][] = $cert['refid'];
358
				}
359
			} else {
360
				$cert = array();
361
				$cert['refid'] = uniqid();
362
				if (isset($id) && $a_cert[$id]) {
363
					$cert = $a_cert[$id];
364
				}
365

    
366
				$cert['descr'] = $pconfig['descr'];
367

    
368
				$old_err_level = error_reporting(0); /* otherwise openssl_ functions throw warnings directly to a page screwing menu tab */
369

    
370
				if ($pconfig['method'] == "import") {
371
					cert_import($cert, $pconfig['cert'], $pconfig['key']);
372
				}
373

    
374
				if ($pconfig['method'] == "internal") {
375
					$dn = array(
376
						'countryName' => $pconfig['dn_country'],
377
						'stateOrProvinceName' => $pconfig['dn_state'],
378
						'localityName' => $pconfig['dn_city'],
379
						'organizationName' => $pconfig['dn_organization'],
380
						'emailAddress' => $pconfig['dn_email'],
381
						'commonName' => $pconfig['dn_commonname']);
382
					if (count($altnames)) {
383
						$altnames_tmp = "";
384
						foreach ($altnames as $altname) {
385
							$altnames_tmp[] = "{$altname['type']}:{$altname['value']}";
386
						}
387
						$dn['subjectAltName'] = implode(",", $altnames_tmp);
388
					}
389
					if (!cert_create($cert, $pconfig['caref'], $pconfig['keylen'],
390
						$pconfig['lifetime'], $dn, $pconfig['type'], $pconfig['digest_alg'])) {
391
						while ($ssl_err = openssl_error_string()) {
392
							$input_errors = array();
393
							array_push($input_errors, "openssl library returns: " . $ssl_err);
394
						}
395
					}
396
				}
397

    
398
				if ($pconfig['method'] == "external") {
399
					$dn = array(
400
						'countryName' => $pconfig['csr_dn_country'],
401
						'stateOrProvinceName' => $pconfig['csr_dn_state'],
402
						'localityName' => $pconfig['csr_dn_city'],
403
						'organizationName' => $pconfig['csr_dn_organization'],
404
						'emailAddress' => $pconfig['csr_dn_email'],
405
						'commonName' => $pconfig['csr_dn_commonname']);
406
					if (count($altnames)) {
407
						$altnames_tmp = "";
408
						foreach ($altnames as $altname) {
409
							$altnames_tmp[] = "{$altname['type']}:{$altname['value']}";
410
						}
411
						$dn['subjectAltName'] = implode(",", $altnames_tmp);
412
					}
413
					if (!csr_generate($cert, $pconfig['csr_keylen'], $dn, $pconfig['csr_digest_alg'])) {
414
						while ($ssl_err = openssl_error_string()) {
415
							$input_errors = array();
416
							array_push($input_errors, "openssl library returns: " . $ssl_err);
417
						}
418
					}
419
				}
420
				error_reporting($old_err_level);
421

    
422
				if (isset($id) && $a_cert[$id]) {
423
					$a_cert[$id] = $cert;
424
				} else {
425
					$a_cert[] = $cert;
426
				}
427
				if (isset($a_user) && isset($userid)) {
428
					$a_user[$userid]['cert'][] = $cert['refid'];
429
				}
430
			}
431

    
432
			if (!$input_errors) {
433
				write_config();
434
			}
435

    
436
			if ($userid) {
437
				post_redirect("system_usermanager.php", array('act' => 'edit', 'userid' => $userid));
438
				exit;
439
			}
440
		}
441
	}
442

    
443
	if ($_POST['save'] == gettext("Update")) {
444
		unset($input_errors);
445
		$pconfig = $_POST;
446

    
447
		/* input validation */
448
		$reqdfields = explode(" ", "descr cert");
449
		$reqdfieldsn = array(
450
		gettext("Descriptive name"),
451
		gettext("Final Certificate data"));
452

    
453
		do_input_validation($_POST, $reqdfields, $reqdfieldsn, $input_errors);
454

    
455
		if (preg_match("/[\?\>\<\&\/\\\"\']/", $_POST['descr'])) {
456
			array_push($input_errors, "The field 'Descriptive Name' contains invalid characters.");
457
		}
458

    
459
//		old way
460
		/* make sure this csr and certificate subjects match */
461
//		$subj_csr = csr_get_subject($pconfig['csr'], false);
462
//		$subj_cert = cert_get_subject($pconfig['cert'], false);
463
//
464
//		if (!isset($_POST['ignoresubjectmismatch']) && !($_POST['ignoresubjectmismatch'] == "yes")) {
465
//			if (strcmp($subj_csr, $subj_cert)) {
466
//				$input_errors[] = sprintf(gettext("The certificate subject '%s' does not match the signing request subject."), $subj_cert);
467
//				$subject_mismatch = true;
468
//			}
469
//		}
470
		$mod_csr = csr_get_modulus($pconfig['csr'], false);
471
		$mod_cert = cert_get_modulus($pconfig['cert'], false);
472

    
473
		if (strcmp($mod_csr, $mod_cert)) {
474
			// simply: if the moduli don't match, then the private key and public key won't match
475
			$input_errors[] = sprintf(gettext("The certificate modulus does not match the signing request modulus."), $subj_cert);
476
			$subject_mismatch = true;
477
		}
478

    
479
		/* if this is an AJAX caller then handle via JSON */
480
		if (isAjax() && is_array($input_errors)) {
481
			input_errors2Ajax($input_errors);
482
			exit;
483
		}
484

    
485
		/* save modifications */
486
		if (!$input_errors) {
487

    
488
			$cert = $a_cert[$id];
489

    
490
			$cert['descr'] = $pconfig['descr'];
491

    
492
			csr_complete($cert, $pconfig['cert']);
493

    
494
			$a_cert[$id] = $cert;
495

    
496
			write_config();
497

    
498
			pfSenseHeader("system_certmanager.php");
499
		}
500
	}
501
}
502

    
503
include("head.inc");
504

    
505
if ($input_errors)
506
	print_input_errors($input_errors);
507
if ($savemsg)
508
	print_info_box($savemsg);
509

    
510
$tab_array = array();
511
$tab_array[] = array(gettext("CAs"), false, "system_camanager.php");
512
$tab_array[] = array(gettext("Certificates"), true, "system_certmanager.php");
513
$tab_array[] = array(gettext("Certificate Revocation"), false, "system_crlmanager.php");
514
display_top_tabs($tab_array);
515

    
516
// Load valid country codes
517
$dn_cc = array();
518
if (file_exists("/etc/ca_countries")){
519
	$dn_cc_file=file("/etc/ca_countries");
520
	foreach($dn_cc_file as $line)
521
		if (preg_match('/^(\S*)\s(.*)$/', $line, $matches))
522
			array_push($dn_cc, $matches[1]);
523
}
524

    
525
if (!($act == "new" || (($_POST['save'] == gettext("Save")) && $input_errors)))
526
{
527
?>
528
<div class="table-responsive">
529
<table class="table table-striped table-hover">
530
	<thead>
531
		<tr>
532
			<th><?=gettext("Name")?></th>
533
			<th><?=gettext("Issuer")?></th>
534
			<th><?=gettext("Distinguished Name")?></th>
535
			<th><?=gettext("In Use")?></th>
536
			<th></th>
537
		</tr>
538
	</thead>
539
	<tbody>
540
<?php
541
foreach($a_cert as $i => $cert):
542
	$name = htmlspecialchars($cert['descr']);
543

    
544
	if ($cert['crt']) {
545
		$subj = cert_get_subject($cert['crt']);
546
		$issuer = cert_get_issuer($cert['crt']);
547
		$purpose = cert_get_purpose($cert['crt']);
548
		list($startdate, $enddate) = cert_get_dates($cert['crt']);
549

    
550
		if ($subj==$issuer)
551
			$caname = '<i>'. gettext("self-signed") .'</i>';
552
		else
553
			$caname = '<i>'. gettext("external").'</i>';
554

    
555
		$subj = htmlspecialchars($subj);
556
	}
557

    
558
	if ($cert['csr']) {
559
		$subj = htmlspecialchars(csr_get_subject($cert['csr']));
560
		$caname = "<em>" . gettext("external - signature pending") . "</em>";
561
	}
562

    
563
	$ca = lookup_ca($cert['caref']);
564
	if ($ca)
565
		$caname = $ca['descr'];
566
?>
567
		<tr>
568
			<td>
569
				<?=$name?>
570
				<?php if ($cert['type']): ?>
571
					<i><?=$cert_types[$cert['type']]?></i>
572
				<?php endif?>
573
				<?php if (is_array($purpose)): ?>
574
					CA: <b><?=$purpose['ca']?></b>, Server: <b><?=$purpose['server']?></b>
575
				<?php endif?>
576
			</td>
577
			<td><?=$caname?></td>
578
			<td>
579
				<?=$subj?>
580
				<br />
581
				<small>
582
					<?=gettext("Valid From")?>: <b><?=$startdate ?></b>, <?=gettext("Valid Until")?>: <b><?=$enddate ?></b>
583
				</small>
584
			</td>
585
			<td>
586
				<?php if (is_cert_revoked($cert)): ?>
587
					<i>Revoked </i>
588
				<?php endif?>
589
				<?php if (is_webgui_cert($cert['refid'])): ?>
590
					webConfigurator
591
				<?php endif?>
592
				<?php if (is_user_cert($cert['refid'])): ?>
593
					User Cert
594
				<?php endif?>
595
				<?php if (is_openvpn_server_cert($cert['refid'])): ?>
596
					OpenVPN Server
597
				<?php endif?>
598
				<?php if (is_openvpn_client_cert($cert['refid'])): ?>
599
					OpenVPN Client
600
				<?php endif?>
601
				<?php if (is_ipsec_cert($cert['refid'])): ?>
602
					IPsec Tunnel
603
				<?php endif?>
604
				<?php if (is_captiveportal_cert($cert['refid'])): ?>
605
					Captive Portal
606
				<?php endif?>
607
			</td>
608
			<td>
609
				<a href="system_certmanager.php?act=exp&amp;id=<?=$i?>" class="btn btn-xs btn-default">
610
					<?=gettext("export")?>
611
				</a>
612
				<a href="system_certmanager.php?act=key&amp;id=<?=$i?>" class="btn btn-xs btn-default">
613
					<?=gettext("export key")?>
614
				</a>
615
				<a href="system_certmanager.php?act=p12&amp;id=<?=$i?>" class="btn btn-xs btn-default">
616
					<?=gettext("export p12")?>
617
				</a>
618
				<?php if (!cert_in_use($cert['refid'])): ?>
619
					<a href="system_certmanager.php?act=del&amp;id=<?=$i?>" class="btn btn-xs btn-danger">
620
						<?=gettext("delete")?>
621
					</a>
622
				<?php endif?>
623
				<?php if ($cert['csr']): ?>
624
					<a href="system_certmanager.php?act=csr&amp;id=<?=$i?>" class="btn btn-xs btn-default">
625
						<?=gettext("update csr")?>
626
					</a>
627
				<?php endif?>
628
			</td>
629
		</tr>
630
<?php endforeach; ?>
631
	</tbody>
632
</table>
633
</div>
634

    
635
<nav class="action-buttons">
636
	<a href="?act=new" class="btn btn-success">add new</a>
637
</nav>
638
<?
639
	include("foot.inc");
640
	exit;
641
}
642

    
643
require('classes/Form.class.php');
644
$form = new Form;
645

    
646
if ($act == "csr" || (($_POST['save'] == gettext("Update")) && $input_errors))
647
{
648
	$form->setAction('system_certmanager.php?act=csr');
649

    
650
	$section = new Form_Section('Complete Signing Request');
651

    
652
	if (isset($id) && $a_cert[$id])
653
	{
654
		$form->addGlobal(new Form_Input(
655
			'id',
656
			null,
657
			'hidden',
658
			$id
659
		));
660
	}
661

    
662
	$section->addInput(new Form_Input(
663
		'descr',
664
		'Descriptive name',
665
		'text',
666
		$pconfig['descr']
667
	));
668

    
669
	$section->addInput(new Form_Textarea(
670
		'csr',
671
		'Signing request data',
672
		$pconfig['csr']
673
	))->setReadonly()->setHelp('Copy the certificate signing data from here and '.
674
		'forward it to your certificate authority for signing.');
675

    
676
	$section->addInput(new Form_Textarea(
677
		'cert',
678
		'Final certificate data',
679
		$pconfig["cert"]
680
	))->setHelp('Paste the certificate received from your certificate authority here.');
681

    
682
	$form->add($section);
683
	print $form;
684

    
685
	include("foot.inc");
686
	exit;
687
}
688

    
689
$form->setAction('system_certmanager.php?act=edit');
690

    
691
if (isset($userid) && $a_user)
692
{
693
	$form->addGlobal(new Form_Input(
694
		'userid',
695
		null,
696
		'hidden',
697
		$userid
698
	));
699
}
700

    
701
if (isset($id) && $a_cert[$id])
702
{
703
	$form->addGlobal(new Form_Input(
704
		'id',
705
		null,
706
		'hidden',
707
		$id
708
	));
709
}
710

    
711
$section = new Form_Section('Add a new certificate');
712

    
713
if (!isset($id))
714
{
715
	$section->addInput(new Form_Select(
716
		'method',
717
		'Method',
718
		$pconfig['method'],
719
		$cert_methods
720
	))->toggles();
721
}
722

    
723
$section->addInput(new Form_Input(
724
	'descr',
725
	'Descriptive name',
726
	'text',
727
	($a_user && empty($pconfig['descr'])) ? $a_user[$userid]['name'] : $pconfig['descr']
728
))->addClass('toggle-existing');
729

    
730
$form->add($section);
731
$section = new Form_Section('Import Certificate');
732
$section->addClass('toggle-import collapse');
733

    
734
$section->addInput(new Form_Textarea(
735
	'cert',
736
	'Certificate data',
737
	$pconfig['cert']
738
))->setHelp('Paste a certificate in X.509 PEM format here.');
739

    
740
$section->addInput(new Form_Textarea(
741
	'key',
742
	'Private key data',
743
	$pconfig['key']
744
))->setHelp('Paste a private key in X.509 PEM format here.');
745

    
746
$form->add($section);
747
$section = new Form_Section('Internal Certificate');
748
$section->addClass('toggle-internal collapse');
749

    
750
if (!$internal_ca_count)
751
{
752
	$section->addInput(new Form_StaticText(
753
		'Certificate authority',
754
		gettext('No internal Certificate Authorities have been defined. You must').
755
		'<a href="system_camanager.php?act=new&amp;method=internal">'. gettext("create") .'</a>'.
756
		gettext('an internal CA before creating an internal certificate.')
757
	));
758
}
759
else
760
{
761
	$allCas = array();
762
	foreach ($a_ca as $ca)
763
	{
764
		if (!$ca['prv'])
765
				continue;
766

    
767
		$allCas[ $ca['refid'] ] = $ca['descr'];
768
	}
769

    
770
	$section->addInput(new Form_Select(
771
		'caref',
772
		'Certificate authority',
773
		$pconfig['caref'],
774
		$allCas
775
	));
776
}
777

    
778
$section->addInput(new Form_Select(
779
	'keylen',
780
	'Key length',
781
	$pconfig['keylen'],
782
	$cert_keylens
783
));
784

    
785
$section->addInput(new Form_Select(
786
	'digest_alg',
787
	'Digest Algorithm',
788
	$pconfig['digest_alg'],
789
	$openssl_digest_algs
790
))->setHelp('NOTE: It is recommended to use an algorithm stronger than '.
791
	'SHA1 when possible.") ?>');
792

    
793
$section->addInput(new Form_Select(
794
	'type',
795
	'Certificate Type',
796
	$pconfig['type'],
797
	$cert_types
798
))->setHelp('Type of certificate to generate. Used for placing '.
799
	'restrictions on the usage of the generated certificate.');
800

    
801
$section->addInput(new Form_Input(
802
	'lifetime',
803
	'Lifetime (days)',
804
	'number',
805
	$pconfig['lifetime']
806
));
807

    
808
$section->addInput(new Form_Select(
809
	'dn_country',
810
	'Country Code',
811
	$pconfig['dn_country'],
812
	$dn_cc
813
));
814

    
815
$section->addInput(new Form_Input(
816
	'dn_state',
817
	'State or Province',
818
	'text',
819
	$pconfig['dn_state'],
820
	['placeholder' => 'e.g. Texas']
821
));
822

    
823
$section->addInput(new Form_Input(
824
	'dn_city',
825
	'City',
826
	'text',
827
	$pconfig['dn_city'],
828
	['placeholder' => 'e.g. Austin']
829
));
830

    
831
$section->addInput(new Form_Input(
832
	'dn_organization',
833
	'Organization',
834
	'text',
835
	$pconfig['dn_organization'],
836
	['placeholder' => 'e.g. My Company Inc.']
837
));
838

    
839
$section->addInput(new Form_Input(
840
	'dn_email',
841
	'Email Address',
842
	'email',
843
	$pconfig['dn_email'],
844
	['placeholder' => 'e.g. admin@mycompany.com']
845
));
846

    
847
$section->addInput(new Form_Input(
848
	'dn_commonname',
849
	'Common Name',
850
	'text',
851
	$pconfig['dn_commonname'],
852
	['placeholder' => 'e.g. internal-ca']
853
));
854

    
855
$group = new Form_Group('Alternative Names');
856

    
857
if (empty($pconfig['altnames']['item']))
858
{
859
	$pconfig['altnames']['item'] = array(
860
		array('type' => null, 'value' => null)
861
	);
862
}
863

    
864
foreach ($pconfig['altnames']['item'] as $item)
865
{
866
	$group->add(new Form_Select(
867
		'altname_type',
868
		'Type',
869
		$item['type'],
870
		array(
871
			'DNS' => 'FQDN or Hostname',
872
			'IP' => 'IP address',
873
			'URI' => 'URI',
874
			'email' => 'email address',
875
		)
876
	));
877

    
878
	$group->add(new Form_Input(
879
		'altname_value',
880
		'Type',
881
		'text',
882
		$item['value']
883
	));
884

    
885
	$group->enableDuplication();
886
}
887

    
888
$section->add($group);
889

    
890
$form->add($section);
891
$section = new Form_Section('External Signing Request');
892
$section->addClass('toggle-external collapse');
893

    
894
$section->addInput(new Form_Select(
895
	'csr_keylen',
896
	'Key length',
897
	$pconfig['csr_keylen'],
898
	$cert_keylens
899
));
900

    
901
$section->addInput(new Form_Select(
902
	'csr_digest_alg',
903
	'Digest Algorithm',
904
	$pconfig['csr_digest_alg'],
905
	$openssl_digest_algs
906
))->setHelp('NOTE: It is recommended to use an algorithm stronger than '.
907
	'SHA1 when possible');
908

    
909
$section->addInput(new Form_Select(
910
	'dn_country',
911
	'Country Code',
912
	$pconfig['dn_country'],
913
	$dn_cc
914
));
915

    
916
$section->addInput(new Form_Input(
917
	'csr_dn_state',
918
	'State or Province',
919
	'text',
920
	$pconfig['csr_dn_state'],
921
	['placeholder' => 'e.g. Texas']
922
));
923

    
924
$section->addInput(new Form_Input(
925
	'csr_dn_city',
926
	'City',
927
	'text',
928
	$pconfig['csr_dn_city'],
929
	['placeholder' => 'e.g. Austin']
930
));
931

    
932
$section->addInput(new Form_Input(
933
	'csr_dn_organization',
934
	'Organization',
935
	'text',
936
	$pconfig['csr_dn_organization'],
937
	['placeholder' => 'e.g. My Company Inc.']
938
));
939

    
940
$section->addInput(new Form_Input(
941
	'csr_dn_email',
942
	'Email Address',
943
	'email',
944
	$pconfig['csr_dn_email'],
945
	['placeholder' => 'e.g. admin@mycompany.com']
946
));
947

    
948
$section->addInput(new Form_Input(
949
	'csr_dn_commonname',
950
	'Common Name',
951
	'text',
952
	$pconfig['csr_dn_commonname'],
953
	['placeholder' => 'e.g. internal-ca']
954
));
955

    
956
$form->add($section);
957
$section = new Form_Section('Choose an Existing Certificate');
958
$section->addClass('toggle-existing collapse');
959

    
960
$existCerts = array();
961
foreach ($config['cert'] as $cert)
962
{
963
	if (isset($userid) && in_array($cert['refid'], $config['system']['user'][$userid]['cert']))
964
		continue;
965

    
966
	$ca = lookup_ca($cert['caref']);
967
	if ($ca)
968
		$cert['descr'] .= " (CA: {$ca['descr']})";
969

    
970
	if (cert_in_use($cert['refid']))
971
		$cert['descr'] .= " <i>In Use</i>";
972
	if (is_cert_revoked($cert))
973
		$cert['descr'] .= " <b>Revoked</b>";
974

    
975
	$existCerts[ $cert['refid'] ] = $cert['descr'];
976
}
977

    
978
$section->addInput(new Form_Select(
979
	'certref',
980
	'Existing Certificates',
981
	$pconfig['certref'],
982
	$existCerts
983
));
984

    
985
$form->add($section);
986
print $form;
987

    
988
?>
989
<nav class="action-buttons">
990
	<a href="system_certmanager.php?act=new">
991
		<?=gettext("add or import certificate")?>
992
	</a>
993
</nav>
994

    
995
<?php include('foot.inc');
(196-196/238)