Project

General

Profile

Download (26.7 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

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

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

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

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

    
122

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

    
133
if ($act == "exp") {
134

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

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

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

    
151
if ($act == "key") {
152

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

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

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

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

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

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

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

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

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

    
198
if ($act == "csr") {
199

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

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

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

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

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

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

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

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

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

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

    
312
			/* Make sure we do not have invalid characters in the fields for the certificate */
313

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

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

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

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

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

    
353
		/* save modifications */
354
		if (!$input_errors) {
355

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

    
368
				$cert['descr'] = $pconfig['descr'];
369

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

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

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

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

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

    
434
			if (!$input_errors) {
435
				write_config();
436
			}
437

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

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

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

    
455
		do_input_validation($_POST, $reqdfields, $reqdfieldsn, $input_errors);
456

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

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

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

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

    
487
		/* save modifications */
488
		if (!$input_errors) {
489

    
490
			$cert = $a_cert[$id];
491

    
492
			$cert['descr'] = $pconfig['descr'];
493

    
494
			csr_complete($cert, $pconfig['cert']);
495

    
496
			$a_cert[$id] = $cert;
497

    
498
			write_config();
499

    
500
			pfSenseHeader("system_certmanager.php");
501
		}
502
	}
503
}
504

    
505
include("head.inc");
506

    
507
if ($input_errors)
508
	print_input_errors($input_errors);
509
if ($savemsg)
510
	print_info_box($savemsg);
511

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

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

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

    
548
	if ($cert['crt']) {
549
		$subj = cert_get_subject($cert['crt']);
550
		$issuer = cert_get_issuer($cert['crt']);
551
		$purpose = cert_get_purpose($cert['crt']);
552
		list($startdate, $enddate) = cert_get_dates($cert['crt']);
553

    
554
		if ($subj==$issuer)
555
			$caname = '<i>'. gettext("self-signed") .'</i>';
556
		else
557
			$caname = '<i>'. gettext("external").'</i>';
558

    
559
		$subj = htmlspecialchars($subj);
560
	}
561

    
562
	if ($cert['csr']) {
563
		$subj = htmlspecialchars(csr_get_subject($cert['csr']));
564
		$caname = "<em>" . gettext("external - signature pending") . "</em>";
565
	}
566

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

    
639
<nav class="action-buttons">
640
	<a href="?act=new" class="btn btn-success">add new</a>
641
</nav>
642
<?
643
	include("foot.inc");
644
	exit;
645
}
646

    
647
require('classes/Form.class.php');
648
$form = new Form;
649

    
650
if ($act == "csr" || (($_POST['save'] == gettext("Update")) && $input_errors))
651
{
652
	$form->setAction('system_certmanager.php?act=csr');
653

    
654
	$section = new Form_Section('Complete Signing Request');
655

    
656
	if (isset($id) && $a_cert[$id])
657
	{
658
		$form->addGlobal(new Form_Input(
659
			'id',
660
			null,
661
			'hidden',
662
			$id
663
		));
664
	}
665

    
666
	$section->addInput(new Form_Input(
667
		'descr',
668
		'Descriptive name',
669
		'text',
670
		$pconfig['descr']
671
	));
672

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

    
680
	$section->addInput(new Form_Textarea(
681
		'cert',
682
		'Final certificate data',
683
		$pconfig["cert"]
684
	))->setHelp('Paste the certificate received from your certificate authority here.');
685

    
686
	$form->add($section);
687
	print $form;
688

    
689
	include("foot.inc");
690
	exit;
691
}
692

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

    
695
if (isset($userid) && $a_user)
696
{
697
	$form->addGlobal(new Form_Input(
698
		'userid',
699
		null,
700
		'hidden',
701
		$userid
702
	));
703
}
704

    
705
if (isset($id) && $a_cert[$id])
706
{
707
	$form->addGlobal(new Form_Input(
708
		'id',
709
		null,
710
		'hidden',
711
		$id
712
	));
713
}
714

    
715
$section = new Form_Section('Add a new certificate');
716

    
717
if (!isset($id))
718
{
719
	$section->addInput(new Form_Select(
720
		'method',
721
		'Method',
722
		$pconfig['method'],
723
		$cert_methods
724
	))->toggles();
725
}
726

    
727
$section->addInput(new Form_Input(
728
	'descr',
729
	'Descriptive name',
730
	'text',
731
	($a_user && empty($pconfig['descr'])) ? $a_user[$userid]['name'] : $pconfig['descr']
732
))->addClass('toggle-existing');
733

    
734
$form->add($section);
735
$section = new Form_Section('Import Certificate');
736
$section->addClass('toggle-import collapse');
737

    
738
$section->addInput(new Form_Textarea(
739
	'cert',
740
	'Certificate data',
741
	$pconfig['cert']
742
))->setHelp('Paste a certificate in X.509 PEM format here.');
743

    
744
$section->addInput(new Form_Textarea(
745
	'key',
746
	'Private key data',
747
	$pconfig['key']
748
))->setHelp('Paste a private key in X.509 PEM format here.');
749

    
750
$form->add($section);
751
$section = new Form_Section('Internal Certificate');
752
$section->addClass('toggle-internal collapse');
753

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

    
771
		$allCas[ $ca['refid'] ] = $ca['descr'];
772
	}
773

    
774
	$section->addInput(new Form_Select(
775
		'caref',
776
		'Certificate authority',
777
		$pconfig['caref'],
778
		$allCas
779
	));
780
}
781

    
782
$section->addInput(new Form_Select(
783
	'keylen',
784
	'Key length',
785
	$pconfig['keylen'],
786
	array_combine($cert_keylens, $cert_keylens)
787
));
788

    
789
$section->addInput(new Form_Select(
790
	'digest_alg',
791
	'Digest Algorithm',
792
	$pconfig['digest_alg'],
793
	array_combine($openssl_digest_algs, $openssl_digest_algs)
794
))->setHelp('NOTE: It is recommended to use an algorithm stronger than '.
795
	'SHA1 when possible.');
796

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

    
805
$section->addInput(new Form_Input(
806
	'lifetime',
807
	'Lifetime (days)',
808
	'number',
809
	$pconfig['lifetime']
810
));
811

    
812
$section->addInput(new Form_Select(
813
	'dn_country',
814
	'Country Code',
815
	$pconfig['dn_country'],
816
	$dn_cc
817
));
818

    
819
$section->addInput(new Form_Input(
820
	'dn_state',
821
	'State or Province',
822
	'text',
823
	$pconfig['dn_state'],
824
	['placeholder' => 'e.g. Texas']
825
));
826

    
827
$section->addInput(new Form_Input(
828
	'dn_city',
829
	'City',
830
	'text',
831
	$pconfig['dn_city'],
832
	['placeholder' => 'e.g. Austin']
833
));
834

    
835
$section->addInput(new Form_Input(
836
	'dn_organization',
837
	'Organization',
838
	'text',
839
	$pconfig['dn_organization'],
840
	['placeholder' => 'e.g. My Company Inc.']
841
));
842

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

    
851
$section->addInput(new Form_Input(
852
	'dn_commonname',
853
	'Common Name',
854
	'text',
855
	$pconfig['dn_commonname'],
856
	['placeholder' => 'e.g. internal-ca']
857
));
858

    
859
$group = new Form_Group('Alternative Names');
860

    
861
if (empty($pconfig['altnames']['item']))
862
{
863
	$pconfig['altnames']['item'] = array(
864
		array('type' => null, 'value' => null)
865
	);
866
}
867

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

    
882
	$group->add(new Form_Input(
883
		'altname_value',
884
		'Type',
885
		'text',
886
		$item['value']
887
	));
888

    
889
	$group->enableDuplication();
890
}
891

    
892
$section->add($group);
893

    
894
$form->add($section);
895
$section = new Form_Section('External Signing Request');
896
$section->addClass('toggle-external collapse');
897

    
898
$section->addInput(new Form_Select(
899
	'csr_keylen',
900
	'Key length',
901
	$pconfig['csr_keylen'],
902
	$cert_keylens
903
));
904

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

    
913
$section->addInput(new Form_Select(
914
	'dn_country',
915
	'Country Code',
916
	$pconfig['dn_country'],
917
	$dn_cc
918
));
919

    
920
$section->addInput(new Form_Input(
921
	'csr_dn_state',
922
	'State or Province',
923
	'text',
924
	$pconfig['csr_dn_state'],
925
	['placeholder' => 'e.g. Texas']
926
));
927

    
928
$section->addInput(new Form_Input(
929
	'csr_dn_city',
930
	'City',
931
	'text',
932
	$pconfig['csr_dn_city'],
933
	['placeholder' => 'e.g. Austin']
934
));
935

    
936
$section->addInput(new Form_Input(
937
	'csr_dn_organization',
938
	'Organization',
939
	'text',
940
	$pconfig['csr_dn_organization'],
941
	['placeholder' => 'e.g. My Company Inc.']
942
));
943

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

    
952
$section->addInput(new Form_Input(
953
	'csr_dn_commonname',
954
	'Common Name',
955
	'text',
956
	$pconfig['csr_dn_commonname'],
957
	['placeholder' => 'e.g. internal-ca']
958
));
959

    
960
$form->add($section);
961
$section = new Form_Section('Choose an Existing Certificate');
962
$section->addClass('toggle-existing collapse');
963

    
964
$existCerts = array();
965
foreach ($config['cert'] as $cert)
966
{
967
	if (isset($userid) && in_array($cert['refid'], $config['system']['user'][$userid]['cert']))
968
		continue;
969

    
970
	$ca = lookup_ca($cert['caref']);
971
	if ($ca)
972
		$cert['descr'] .= " (CA: {$ca['descr']})";
973

    
974
	if (cert_in_use($cert['refid']))
975
		$cert['descr'] .= " <i>In Use</i>";
976
	if (is_cert_revoked($cert))
977
		$cert['descr'] .= " <b>Revoked</b>";
978

    
979
	$existCerts[ $cert['refid'] ] = $cert['descr'];
980
}
981

    
982
$section->addInput(new Form_Select(
983
	'certref',
984
	'Existing Certificates',
985
	$pconfig['certref'],
986
	$existCerts
987
));
988

    
989
$form->add($section);
990
print $form;
991

    
992
?>
993
<script>
994
//<![CDATA[
995
events.push(function(){
996
<?php if ($internal_ca_count): ?>
997
	function internalca_change() {
998

    
999
		caref = $('#caref').val();
1000

    
1001
		switch (caref) {
1002
<?php
1003
			foreach ($a_ca as $ca):
1004
				if (!$ca['prv']) {
1005
					continue;
1006
				}
1007

    
1008
				$subject = cert_get_subject_array($ca['crt']);
1009

    
1010
?>
1011
				case "<?=$ca['refid'];?>":
1012
					$('#dn_country').val("<?=$subject[0]['v'];?>");
1013
					$('#dn_state').val("<?=$subject[1]['v'];?>");
1014
					$('#dn_city').val("<?=$subject[2]['v'];?>");
1015
					$('#dn_organization').val("<?=$subject[3]['v'];?>");
1016
					$('#dn_email').val("<?=$subject[4]['v'];?>");
1017
					break;
1018
<?php
1019
			endforeach;
1020
?>
1021
		}
1022
	}
1023

    
1024
	// On click . .
1025
	$('#caref').on('change', function() {
1026
		internalca_change();
1027
	});
1028

    
1029
	// On page load . .
1030
	internalca_change();
1031

    
1032
<?php endif; ?>
1033

    
1034

    
1035
});
1036
//]]>
1037
</script>
1038
<?php
1039
include('foot.inc');
(195-195/237)