Project

General

Profile

Download (23.6 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
 * system_camanager.php
4
 *
5
 * part of pfSense (https://www.pfsense.org)
6
 * Copyright (c) 2004-2013 BSD Perimeter
7
 * Copyright (c) 2013-2016 Electric Sheep Fencing
8
 * Copyright (c) 2014-2019 Rubicon Communications, LLC (Netgate)
9
 * Copyright (c) 2008 Shrew Soft Inc
10
 * All rights reserved.
11
 *
12
 * Licensed under the Apache License, Version 2.0 (the "License");
13
 * you may not use this file except in compliance with the License.
14
 * You may obtain a copy of the License at
15
 *
16
 * http://www.apache.org/licenses/LICENSE-2.0
17
 *
18
 * Unless required by applicable law or agreed to in writing, software
19
 * distributed under the License is distributed on an "AS IS" BASIS,
20
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21
 * See the License for the specific language governing permissions and
22
 * limitations under the License.
23
 */
24

    
25
##|+PRIV
26
##|*IDENT=page-system-camanager
27
##|*NAME=System: CA Manager
28
##|*DESCR=Allow access to the 'System: CA Manager' page.
29
##|*MATCH=system_camanager.php*
30
##|-PRIV
31

    
32
require_once("guiconfig.inc");
33
require_once("certs.inc");
34
require_once("pfsense-utils.inc");
35

    
36
$ca_methods = array(
37
	"internal" => gettext("Create an internal Certificate Authority"),
38
	"existing" => gettext("Import an existing Certificate Authority"),
39
	"intermediate" => gettext("Create an intermediate Certificate Authority"));
40

    
41
$ca_keylens = array("1024", "2048", "3072", "4096", "6144", "7680", "8192", "15360", "16384");
42
$ca_keytypes = array("RSA", "ECDSA");
43
global $openssl_digest_algs;
44
global $cert_strict_values;
45
$openssl_ecnames = openssl_get_curve_names();
46

    
47
if (isset($_REQUEST['id']) && is_numericint($_REQUEST['id'])) {
48
	$id = $_REQUEST['id'];
49
}
50

    
51
init_config_arr(array('ca'));
52
$a_ca = &$config['ca'];
53

    
54
init_config_arr(array('cert'));
55
$a_cert = &$config['cert'];
56

    
57
init_config_arr(array('crl'));
58
$a_crl = &$config['crl'];
59

    
60
if ($_REQUEST['act']) {
61
	$act = $_REQUEST['act'];
62
}
63

    
64
if ($_POST['act'] == "del") {
65

    
66
	if (!isset($a_ca[$id])) {
67
		pfSenseHeader("system_camanager.php");
68
		exit;
69
	}
70

    
71
	/* Only remove CA reference when deleting. It can be reconnected if a new matching CA is imported */
72
	$index = count($a_cert) - 1;
73
	for (;$index >= 0; $index--) {
74
		if ($a_cert[$index]['caref'] == $a_ca[$id]['refid']) {
75
			unset($a_cert[$index]['caref']);
76
		}
77
	}
78

    
79
	/* Remove any CRLs for this CA, there is no way to recover the connection once the CA has been removed. */
80
	$index = count($a_crl) - 1;
81
	for (;$index >= 0; $index--) {
82
		if ($a_crl[$index]['caref'] == $a_ca[$id]['refid']) {
83
			unset($a_crl[$index]);
84
		}
85
	}
86

    
87
	$name = $a_ca[$id]['descr'];
88
	unset($a_ca[$id]);
89
	write_config();
90
	$savemsg = sprintf(gettext("Certificate Authority %s and its CRLs (if any) successfully deleted."), htmlspecialchars($name));
91
	pfSenseHeader("system_camanager.php");
92
	exit;
93
}
94

    
95
if ($act == "edit") {
96
	if (!$a_ca[$id]) {
97
		pfSenseHeader("system_camanager.php");
98
		exit;
99
	}
100
	$pconfig['method'] = 'existing';
101
	$pconfig['descr']  = $a_ca[$id]['descr'];
102
	$pconfig['refid']  = $a_ca[$id]['refid'];
103
	$pconfig['cert']   = base64_decode($a_ca[$id]['crt']);
104
	$pconfig['serial'] = $a_ca[$id]['serial'];
105
	if (!empty($a_ca[$id]['prv'])) {
106
		$pconfig['key'] = base64_decode($a_ca[$id]['prv']);
107
	}
108
}
109

    
110
if ($act == "new") {
111
	$pconfig['method'] = $_POST['method'];
112
	$pconfig['keytype'] = "RSA";
113
	$pconfig['keylen'] = "2048";
114
	$pconfig['ecname'] = "brainpoolP256r1";
115
	$pconfig['digest_alg'] = "sha256";
116
	$pconfig['lifetime'] = "3650";
117
	$pconfig['dn_commonname'] = "internal-ca";
118
}
119

    
120
if ($act == "exp") {
121

    
122
	if (!$a_ca[$id]) {
123
		pfSenseHeader("system_camanager.php");
124
		exit;
125
	}
126

    
127
	$exp_name = urlencode("{$a_ca[$id]['descr']}.crt");
128
	$exp_data = base64_decode($a_ca[$id]['crt']);
129
	$exp_size = strlen($exp_data);
130

    
131
	header("Content-Type: application/octet-stream");
132
	header("Content-Disposition: attachment; filename={$exp_name}");
133
	header("Content-Length: $exp_size");
134
	echo $exp_data;
135
	exit;
136
}
137

    
138
if ($act == "expkey") {
139

    
140
	if (!$a_ca[$id]) {
141
		pfSenseHeader("system_camanager.php");
142
		exit;
143
	}
144

    
145
	$exp_name = urlencode("{$a_ca[$id]['descr']}.key");
146
	$exp_data = base64_decode($a_ca[$id]['prv']);
147
	$exp_size = strlen($exp_data);
148

    
149
	header("Content-Type: application/octet-stream");
150
	header("Content-Disposition: attachment; filename={$exp_name}");
151
	header("Content-Length: $exp_size");
152
	echo $exp_data;
153
	exit;
154
}
155

    
156
if ($_POST['save']) {
157

    
158
	unset($input_errors);
159
	$input_errors = array();
160
	$pconfig = $_POST;
161

    
162
	/* input validation */
163
	if ($pconfig['method'] == "existing") {
164
		$reqdfields = explode(" ", "descr cert");
165
		$reqdfieldsn = array(
166
			gettext("Descriptive name"),
167
			gettext("Certificate data"));
168
		if ($_POST['cert'] && (!strstr($_POST['cert'], "BEGIN CERTIFICATE") || !strstr($_POST['cert'], "END CERTIFICATE"))) {
169
			$input_errors[] = gettext("This certificate does not appear to be valid.");
170
		}
171
		if ($_POST['key'] && strstr($_POST['key'], "ENCRYPTED")) {
172
			$input_errors[] = gettext("Encrypted private keys are not yet supported.");
173
		}
174
		if (!$input_errors && !empty($_POST['key']) && cert_get_publickey($_POST['cert'], false) != cert_get_publickey($_POST['key'], false, 'prv')) {
175
			$input_errors[] = gettext("The submitted private key does not match the submitted certificate data.");
176
		}
177
		/* we must ensure the certificate is capable of acting as a CA
178
		 * https://redmine.pfsense.org/issues/7885
179
		 */
180
		if (!$input_errors) {
181
			$purpose = cert_get_purpose($_POST['cert'], false);
182
			if ($purpose['ca'] != 'Yes') {
183
				$input_errors[] = gettext("The submitted certificate does not appear to be a Certificate Authority, import it on the Certificates tab instead.");
184
			}
185
		}
186
	}
187
	if ($pconfig['method'] == "internal") {
188
		$reqdfields = explode(" ",
189
			"descr keylen ecname keytype lifetime dn_commonname");
190
		$reqdfieldsn = array(
191
			gettext("Descriptive name"),
192
			gettext("Key length"),
193
			gettext("Elliptic Curve Name"),
194
			gettext("Key type"),
195
			gettext("Lifetime"),
196
			gettext("Common Name"));
197
	}
198
	if ($pconfig['method'] == "intermediate") {
199
		$reqdfields = explode(" ",
200
			"descr caref keylen ecname keytype lifetime dn_commonname");
201
		$reqdfieldsn = array(
202
			gettext("Descriptive name"),
203
			gettext("Signing Certificate Authority"),
204
			gettext("Key length"),
205
			gettext("Elliptic Curve Name"),
206
			gettext("Key type"),
207
			gettext("Lifetime"),
208
			gettext("Common Name"));
209
	}
210

    
211
	do_input_validation($_POST, $reqdfields, $reqdfieldsn, $input_errors);
212
	if ($pconfig['method'] != "existing") {
213
		/* Make sure we do not have invalid characters in the fields for the certificate */
214
		if (preg_match("/[\?\>\<\&\/\\\"\']/", $_POST['descr'])) {
215
			array_push($input_errors, gettext("The field 'Descriptive Name' contains invalid characters."));
216
		}
217
		if (!in_array($_POST["keytype"], $ca_keytypes)) {
218
			array_push($input_errors, gettext("Please select a valid Key Type."));
219
		}
220
		if (!in_array($_POST["keylen"], $ca_keylens)) {
221
			array_push($input_errors, gettext("Please select a valid Key Length."));
222
		}
223
		if (!in_array($_POST["ecname"], $openssl_ecnames)) {
224
			array_push($input_errors, gettext("Please select a valid Elliptic Curve Name."));
225
		}
226
		if (!in_array($_POST["digest_alg"], $openssl_digest_algs)) {
227
			array_push($input_errors, gettext("Please select a valid Digest Algorithm."));
228
		}
229
	}
230

    
231
	/* save modifications */
232
	if (!$input_errors) {
233
		$ca = array();
234
		if (!isset($pconfig['refid']) || empty($pconfig['refid'])) {
235
			$ca['refid'] = uniqid();
236
		} else {
237
			$ca['refid'] = $pconfig['refid'];
238
		}
239

    
240
		if (isset($id) && $a_ca[$id]) {
241
			$ca = $a_ca[$id];
242
		}
243

    
244
		$ca['descr'] = $pconfig['descr'];
245

    
246
		if ($act == "edit") {
247
			$ca['descr']  = $pconfig['descr'];
248
			$ca['refid']  = $pconfig['refid'];
249
			$ca['serial'] = $pconfig['serial'];
250
			$ca['crt']	  = base64_encode($pconfig['cert']);
251
			if (!empty($pconfig['key'])) {
252
				$ca['prv']	  = base64_encode($pconfig['key']);
253
			}
254
		} else {
255
			$old_err_level = error_reporting(0); /* otherwise openssl_ functions throw warnings directly to a page screwing menu tab */
256
			if ($pconfig['method'] == "existing") {
257
				ca_import($ca, $pconfig['cert'], $pconfig['key'], $pconfig['serial']);
258
			} else if ($pconfig['method'] == "internal") {
259
				$dn = array('commonName' => cert_escape_x509_chars($pconfig['dn_commonname']));
260
				if (!empty($pconfig['dn_country'])) {
261
					$dn['countryName'] = $pconfig['dn_country'];
262
				}
263
				if (!empty($pconfig['dn_state'])) {
264
					$dn['stateOrProvinceName'] = cert_escape_x509_chars($pconfig['dn_state']);
265
				}
266
				if (!empty($pconfig['dn_city'])) {
267
					$dn['localityName'] = cert_escape_x509_chars($pconfig['dn_city']);
268
				}
269
				if (!empty($pconfig['dn_organization'])) {
270
					$dn['organizationName'] = cert_escape_x509_chars($pconfig['dn_organization']);
271
				}
272
				if (!empty($pconfig['dn_organizationalunit'])) {
273
					$dn['organizationalUnitName'] = cert_escape_x509_chars($pconfig['dn_organizationalunit']);
274
				}
275
				if (!ca_create($ca, $pconfig['keylen'], $pconfig['lifetime'], $dn, $pconfig['digest_alg'], $pconfig['keytype'], $pconfig['ecname'])) {
276
					$input_errors = array();
277
					while ($ssl_err = openssl_error_string()) {
278
						if (strpos($ssl_err, 'NCONF_get_string:no value') === false) {
279
							array_push($input_errors, "openssl library returns: " . $ssl_err);
280
						}
281
					}
282
				}
283
			} else if ($pconfig['method'] == "intermediate") {
284
				$dn = array('commonName' => cert_escape_x509_chars($pconfig['dn_commonname']));
285
				if (!empty($pconfig['dn_country'])) {
286
					$dn['countryName'] = $pconfig['dn_country'];
287
				}
288
				if (!empty($pconfig['dn_state'])) {
289
					$dn['stateOrProvinceName'] = cert_escape_x509_chars($pconfig['dn_state']);
290
				}
291
				if (!empty($pconfig['dn_city'])) {
292
					$dn['localityName'] = cert_escape_x509_chars($pconfig['dn_city']);
293
				}
294
				if (!empty($pconfig['dn_organization'])) {
295
					$dn['organizationName'] = cert_escape_x509_chars($pconfig['dn_organization']);
296
				}
297
				if (!empty($pconfig['dn_organizationalunit'])) {
298
					$dn['organizationalUnitName'] = cert_escape_x509_chars($pconfig['dn_organizationalunit']);
299
				}
300
				if (!ca_inter_create($ca, $pconfig['keylen'], $pconfig['lifetime'], $dn, $pconfig['caref'], $pconfig['digest_alg'], $pconfig['keytype'], $pconfig['ecname'])) {
301
					$input_errors = array();
302
					while ($ssl_err = openssl_error_string()) {
303
						if (strpos($ssl_err, 'NCONF_get_string:no value') === false) {
304
							array_push($input_errors, "openssl library returns: " . $ssl_err);
305
						}
306
					}
307
				}
308
			}
309
			error_reporting($old_err_level);
310
		}
311

    
312
		if (isset($id) && $a_ca[$id]) {
313
			$a_ca[$id] = $ca;
314
		} else {
315
			$a_ca[] = $ca;
316
		}
317

    
318
		if (!$input_errors) {
319
			write_config();
320
			pfSenseHeader("system_camanager.php");
321
		}
322
	}
323
}
324

    
325
$pgtitle = array(gettext("System"), gettext("Certificate Manager"), gettext("CAs"));
326
$pglinks = array("", "system_camanager.php", "system_camanager.php");
327

    
328
if ($act == "new" || $act == "edit" || $act == gettext("Save") || $input_errors) {
329
	$pgtitle[] = gettext('Edit');
330
	$pglinks[] = "@self";
331
}
332
include("head.inc");
333

    
334
if ($input_errors) {
335
	print_input_errors($input_errors);
336
}
337

    
338
if ($savemsg) {
339
	print_info_box($savemsg, 'success');
340
}
341

    
342
$tab_array = array();
343
$tab_array[] = array(gettext("CAs"), true, "system_camanager.php");
344
$tab_array[] = array(gettext("Certificates"), false, "system_certmanager.php");
345
$tab_array[] = array(gettext("Certificate Revocation"), false, "system_crlmanager.php");
346
display_top_tabs($tab_array);
347

    
348
if (!($act == "new" || $act == "edit" || $act == gettext("Save") || $input_errors)) {
349
?>
350
<div class="panel panel-default" id="search-panel">
351
	<div class="panel-heading">
352
		<h2 class="panel-title">
353
			<?=gettext('Search')?>
354
			<span class="widget-heading-icon pull-right">
355
				<a data-toggle="collapse" href="#search-panel_panel-body">
356
					<i class="fa fa-plus-circle"></i>
357
				</a>
358
			</span>
359
		</h2>
360
	</div>
361
	<div id="search-panel_panel-body" class="panel-body collapse in">
362
		<div class="form-group">
363
			<label class="col-sm-2 control-label">
364
				<?=gettext("Search term")?>
365
			</label>
366
			<div class="col-sm-5"><input class="form-control" name="searchstr" id="searchstr" type="text"/></div>
367
			<div class="col-sm-2">
368
				<select id="where" class="form-control">
369
					<option value="0"><?=gettext("Name")?></option>
370
					<option value="1"><?=gettext("Distinguished Name")?></option>
371
					<option value="2" selected><?=gettext("Both")?></option>
372
				</select>
373
			</div>
374
			<div class="col-sm-3">
375
				<a id="btnsearch" title="<?=gettext("Search")?>" class="btn btn-primary btn-sm"><i class="fa fa-search icon-embed-btn"></i><?=gettext("Search")?></a>
376
				<a id="btnclear" title="<?=gettext("Clear")?>" class="btn btn-info btn-sm"><i class="fa fa-undo icon-embed-btn"></i><?=gettext("Clear")?></a>
377
			</div>
378
			<div class="col-sm-10 col-sm-offset-2">
379
				<span class="help-block"><?=gettext('Enter a search string or *nix regular expression to search certificate names and distinguished names.')?></span>
380
			</div>
381
		</div>
382
	</div>
383
</div>
384

    
385
<div class="panel panel-default">
386
	<div class="panel-heading"><h2 class="panel-title"><?=gettext('Certificate Authorities')?></h2></div>
387
	<div class="panel-body">
388
		<div class="table-responsive">
389
		<table id="catable" class="table table-striped table-hover table-rowdblclickedit sortable-theme-bootstrap" data-sortable>
390
			<thead>
391
				<tr>
392
					<th><?=gettext("Name")?></th>
393
					<th><?=gettext("Internal")?></th>
394
					<th><?=gettext("Issuer")?></th>
395
					<th><?=gettext("Certificates")?></th>
396
					<th><?=gettext("Distinguished Name")?></th>
397
					<th><?=gettext("In Use")?></th>
398
					<th><?=gettext("Actions")?></th>
399
				</tr>
400
			</thead>
401
			<tbody>
402
<?php
403
$pluginparams = array();
404
$pluginparams['type'] = 'certificates';
405
$pluginparams['event'] = 'used_ca';
406
$certificates_used_by_packages = pkg_call_plugins('plugin_certificates', $pluginparams);
407

    
408
foreach ($a_ca as $i => $ca):
409
	$name = htmlspecialchars($ca['descr']);
410
	$subj = cert_get_subject($ca['crt']);
411
	$issuer = cert_get_issuer($ca['crt']);
412
	if ($subj == $issuer) {
413
		$issuer_name = gettext("self-signed");
414
	} else {
415
		$issuer_name = gettext("external");
416
	}
417
	$subj = htmlspecialchars(cert_escape_x509_chars($subj, true));
418
	$issuer = htmlspecialchars($issuer);
419
	$certcount = 0;
420

    
421
	$issuer_ca = lookup_ca($ca['caref']);
422
	if ($issuer_ca) {
423
		$issuer_name = $issuer_ca['descr'];
424
	}
425

    
426
	foreach ($a_cert as $cert) {
427
		if ($cert['caref'] == $ca['refid']) {
428
			$certcount++;
429
		}
430
	}
431

    
432
	foreach ($a_ca as $cert) {
433
		if ($cert['caref'] == $ca['refid']) {
434
			$certcount++;
435
		}
436
	}
437
?>
438
				<tr>
439
					<td><?=$name?></td>
440
					<td><i class="fa fa-<?= (!empty($ca['prv'])) ? "check" : "times" ; ?>"></i></td>
441
					<td><i><?=$issuer_name?></i></td>
442
					<td><?=$certcount?></td>
443
					<td>
444
						<?=$subj?>
445
						<?php cert_print_infoblock($ca); ?>
446
						<?php cert_print_dates($ca);?>
447
					</td>
448
					<td class="text-nowrap">
449
						<?php if (is_openvpn_server_ca($ca['refid'])): ?>
450
							<?=gettext("OpenVPN Server")?><br/>
451
						<?php endif?>
452
						<?php if (is_openvpn_client_ca($ca['refid'])): ?>
453
							<?=gettext("OpenVPN Client")?><br/>
454
						<?php endif?>
455
						<?php if (is_ipsec_peer_ca($ca['refid'])): ?>
456
							<?=gettext("IPsec Tunnel")?><br/>
457
						<?php endif?>
458
						<?php if (is_ldap_peer_ca($ca['refid'])): ?>
459
							<?=gettext("LDAP Server")?>
460
						<?php endif?>
461
						<?php echo cert_usedby_description($ca['refid'], $certificates_used_by_packages); ?>
462
					</td>
463
					<td class="text-nowrap">
464
						<a class="fa fa-pencil"	title="<?=gettext("Edit CA")?>"	href="system_camanager.php?act=edit&amp;id=<?=$i?>"></a>
465
						<a class="fa fa-certificate"	title="<?=gettext("Export CA")?>"	href="system_camanager.php?act=exp&amp;id=<?=$i?>"></a>
466
					<?php if ($ca['prv']): ?>
467
						<a class="fa fa-key"	title="<?=gettext("Export key")?>"	href="system_camanager.php?act=expkey&amp;id=<?=$i?>"></a>
468
					<?php endif?>
469
					<?php if (is_cert_locally_renewable($ca)): ?>
470
						<a href="system_certmanager_renew.php?type=ca&amp;refid=<?=$ca['refid']?>" class="fa fa-repeat" title="<?=gettext("Reissue/Renew")?>"></a>
471
					<?php endif ?>
472
					<?php if (!ca_in_use($ca['refid'])): ?>
473
						<a class="fa fa-trash" 	title="<?=gettext("Delete CA and its CRLs")?>"	href="system_camanager.php?act=del&amp;id=<?=$i?>" usepost ></a>
474
					<?php endif?>
475
					</td>
476
				</tr>
477
<?php endforeach; ?>
478
			</tbody>
479
		</table>
480
		</div>
481
	</div>
482
</div>
483

    
484
<nav class="action-buttons">
485
	<a href="?act=new" class="btn btn-success btn-sm">
486
		<i class="fa fa-plus icon-embed-btn"></i>
487
		<?=gettext("Add")?>
488
	</a>
489
</nav>
490
<script type="text/javascript">
491
//<![CDATA[
492

    
493
events.push(function() {
494

    
495
	// Make these controls plain buttons
496
	$("#btnsearch").prop('type', 'button');
497
	$("#btnclear").prop('type', 'button');
498

    
499
	// Search for a term in the entry name and/or dn
500
	$("#btnsearch").click(function() {
501
		var searchstr = $('#searchstr').val().toLowerCase();
502
		var table = $("table tbody");
503
		var where = $('#where').val();
504

    
505
		table.find('tr').each(function (i) {
506
			var $tds = $(this).find('td'),
507
				shortname = $tds.eq(0).text().trim().toLowerCase(),
508
				dn = $tds.eq(4).text().trim().toLowerCase();
509

    
510
			regexp = new RegExp(searchstr);
511
			if (searchstr.length > 0) {
512
				if (!(regexp.test(shortname) && (where != 1)) && !(regexp.test(dn) && (where != 0))) {
513
					$(this).hide();
514
				} else {
515
					$(this).show();
516
				}
517
			} else {
518
				$(this).show();	// A blank search string shows all
519
			}
520
		});
521
	});
522

    
523
	// Clear the search term and unhide all rows (that were hidden during a previous search)
524
	$("#btnclear").click(function() {
525
		var table = $("table tbody");
526

    
527
		$('#searchstr').val("");
528

    
529
		table.find('tr').each(function (i) {
530
			$(this).show();
531
		});
532
	});
533

    
534
	// Hitting the enter key will do the same as clicking the search button
535
	$("#searchstr").on("keyup", function (event) {
536
		if (event.keyCode == 13) {
537
			$("#btnsearch").get(0).click();
538
		}
539
	});
540
});
541
//]]>
542
</script>
543

    
544
<?php
545
	include("foot.inc");
546
	exit;
547
}
548

    
549
$form = new Form;
550
//$form->setAction('system_camanager.php?act=edit');
551
if (isset($id) && $a_ca[$id]) {
552
	$form->addGlobal(new Form_Input(
553
		'id',
554
		null,
555
		'hidden',
556
		$id
557
	));
558
}
559

    
560
if ($act == "edit") {
561
	$form->addGlobal(new Form_Input(
562
		'refid',
563
		null,
564
		'hidden',
565
		$pconfig['refid']
566
	));
567
}
568

    
569
$section = new Form_Section('Create / Edit CA');
570

    
571
$section->addInput(new Form_Input(
572
	'descr',
573
	'*Descriptive name',
574
	'text',
575
	$pconfig['descr']
576
));
577

    
578
if (!isset($id) || $act == "edit") {
579
	$section->addInput(new Form_Select(
580
		'method',
581
		'*Method',
582
		$pconfig['method'],
583
		$ca_methods
584
	))->toggles();
585
}
586

    
587
$form->add($section);
588

    
589
$section = new Form_Section('Existing Certificate Authority');
590
$section->addClass('toggle-existing collapse');
591

    
592
$section->addInput(new Form_Textarea(
593
	'cert',
594
	'*Certificate data',
595
	$pconfig['cert']
596
))->setHelp('Paste a certificate in X.509 PEM format here.');
597

    
598
$section->addInput(new Form_Textarea(
599
	'key',
600
	'Certificate Private Key (optional)',
601
	$pconfig['key']
602
))->setHelp('Paste the private key for the above certificate here. This is '.
603
	'optional in most cases, but is required when generating a '.
604
	'Certificate Revocation List (CRL).');
605

    
606
$section->addInput(new Form_Input(
607
	'serial',
608
	'Serial for next certificate',
609
	'number',
610
	$pconfig['serial']
611
))->setHelp('Enter a decimal number to be used as the serial number for the next '.
612
	'certificate to be created using this CA.');
613

    
614
$form->add($section);
615

    
616
$section = new Form_Section('Internal Certificate Authority');
617
$section->addClass('toggle-internal', 'toggle-intermediate', 'collapse');
618

    
619
$allCas = array();
620
foreach ($a_ca as $ca) {
621
	if (!$ca['prv']) {
622
			continue;
623
	}
624

    
625
	$allCas[ $ca['refid'] ] = $ca['descr'];
626
}
627

    
628
$group = new Form_Group('*Signing Certificate Authority');
629
$group->addClass('toggle-intermediate', 'collapse');
630
$group->add(new Form_Select(
631
	'caref',
632
	null,
633
	$pconfig['caref'],
634
	$allCas
635
));
636
$section->add($group);
637

    
638
$section->addInput(new Form_Select(
639
	'keytype',
640
	'*Key type',
641
	$pconfig['keytype'],
642
	array_combine($ca_keytypes, $ca_keytypes)
643
));
644

    
645
$group = new Form_Group($i == 0 ? '*Key length':'');
646
$group->addClass('rsakeys');
647
$group->add(new Form_Select(
648
	'keylen',
649
	null,
650
	$pconfig['keylen'],
651
	array_combine($ca_keylens, $ca_keylens)
652
))->setHelp('The length to use when generating a new RSA key, in bits. %1$s' .
653
	'The Key Length should not be lower than 2048 or some platforms ' .
654
	'may consider the certificate invalid.', '<br/>');
655
$section->add($group);
656

    
657
$group = new Form_Group($i == 0 ? '*Elliptic Curve Name':'');
658
$group->addClass('ecnames');
659
$group->add(new Form_Select(
660
	'ecname',
661
	null,
662
	$pconfig['ecname'],
663
	array_combine($openssl_ecnames, $openssl_ecnames)
664
));
665
$section->add($group);
666

    
667
$section->addInput(new Form_Select(
668
	'digest_alg',
669
	'*Digest Algorithm',
670
	$pconfig['digest_alg'],
671
	array_combine($openssl_digest_algs, $openssl_digest_algs)
672
))->setHelp('The digest method used when the CA is signed. %1$s' .
673
	'The best practice is to use an algorithm stronger than SHA1. '.
674
	'Some platforms may consider weaker digest algorithms invalid', '<br/>');
675

    
676
$section->addInput(new Form_Input(
677
	'lifetime',
678
	'*Lifetime (days)',
679
	'number',
680
	$pconfig['lifetime']
681
));
682

    
683
$section->addInput(new Form_Input(
684
	'dn_commonname',
685
	'*Common Name',
686
	'text',
687
	$pconfig['dn_commonname'],
688
	['placeholder' => 'e.g. internal-ca']
689
));
690

    
691
$section->addInput(new Form_StaticText(
692
	null,
693
	gettext('The following certificate authority subject components are optional and may be left blank.')
694
));
695

    
696
$section->addInput(new Form_Select(
697
	'dn_country',
698
	'Country Code',
699
	$pconfig['dn_country'],
700
	get_cert_country_codes()
701
));
702

    
703
$section->addInput(new Form_Input(
704
	'dn_state',
705
	'State or Province',
706
	'text',
707
	$pconfig['dn_state'],
708
	['placeholder' => 'e.g. Texas']
709
));
710

    
711
$section->addInput(new Form_Input(
712
	'dn_city',
713
	'City',
714
	'text',
715
	$pconfig['dn_city'],
716
	['placeholder' => 'e.g. Austin']
717
));
718

    
719
$section->addInput(new Form_Input(
720
	'dn_organization',
721
	'Organization',
722
	'text',
723
	$pconfig['dn_organization'],
724
	['placeholder' => 'e.g. My Company Inc']
725
));
726

    
727
$section->addInput(new Form_Input(
728
	'dn_organizationalunit',
729
	'Organizational Unit',
730
	'text',
731
	$pconfig['dn_organizationalunit'],
732
	['placeholder' => 'e.g. My Department Name (optional)']
733
));
734

    
735
$form->add($section);
736

    
737
print $form;
738

    
739
$internal_ca_count = 0;
740
foreach ($a_ca as $ca) {
741
	if ($ca['prv']) {
742
		$internal_ca_count++;
743
	}
744
}
745

    
746
?>
747
<script type="text/javascript">
748
//<![CDATA[
749
events.push(function() {
750
	function change_keytype() {
751
	hideClass('rsakeys', ($('#keytype').val() != 'RSA'));
752
		hideClass('ecnames', ($('#keytype').val() != 'ECDSA'));
753
	}
754

    
755
	$('#keytype').change(function () {
756
		change_keytype();
757
	});
758

    
759
	function check_keylen() {
760
		var min_keylen = <?= $cert_strict_values['min_private_key_bits'] ?>;
761
		var klid = '#keylen';
762
		/* Color the Parent/Label */
763
		if (parseInt($(klid).val()) < min_keylen) {
764
			$(klid).parent().parent().removeClass("text-normal").addClass("text-warning");
765
		} else {
766
			$(klid).parent().parent().removeClass("text-warning").addClass("text-normal");
767
		}
768
		/* Color individual options */
769
		$(klid + " option").filter(function() {
770
			return parseInt($(this).val()) < min_keylen;
771
		}).removeClass("text-normal").addClass("text-warning").siblings().removeClass("text-warning").addClass("text-normal");
772
	}
773

    
774
	function check_digest() {
775
		var weak_algs = <?= json_encode($cert_strict_values['digest_blacklist']) ?>;
776
		var daid = '#digest_alg';
777
		/* Color the Parent/Label */
778
		if (jQuery.inArray($(daid).val(), weak_algs) > -1) {
779
			$(daid).parent().parent().removeClass("text-normal").addClass("text-warning");
780
		} else {
781
			$(daid).parent().parent().removeClass("text-warning").addClass("text-normal");
782
		}
783
		/* Color individual options */
784
		$(daid + " option").filter(function() {
785
			return (jQuery.inArray($(this).val(), weak_algs) > -1);
786
		}).removeClass("text-normal").addClass("text-warning").siblings().removeClass("text-warning").addClass("text-normal");
787
	}
788

    
789
	// ---------- Control change handlers ---------------------------------------------------------
790

    
791
	$('#method').on('change', function() {
792
		check_keylen();
793
		check_digest();
794
	});
795

    
796
	$('#keylen').on('change', function() {
797
		check_keylen();
798
	});
799

    
800
	$('#digest_alg').on('change', function() {
801
		check_digest();
802
	});
803

    
804
	// ---------- On initial page load ------------------------------------------------------------
805
	change_keytype();
806
	check_keylen();
807
	check_digest();
808
});
809
//]]>
810
</script>
811
<?php
812
include('foot.inc');
(192-192/227)