Project

General

Profile

Download (18.1 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-2016 Electric Sheep Fencing, LLC
7
 * Copyright (c) 2008 Shrew Soft Inc
8
 * All rights reserved.
9
 *
10
 * Redistribution and use in source and binary forms, with or without
11
 * modification, are permitted provided that the following conditions are met:
12
 *
13
 * 1. Redistributions of source code must retain the above copyright notice,
14
 *    this list of conditions and the following disclaimer.
15
 *
16
 * 2. Redistributions in binary form must reproduce the above copyright
17
 *    notice, this list of conditions and the following disclaimer in
18
 *    the documentation and/or other materials provided with the
19
 *    distribution.
20
 *
21
 * 3. All advertising materials mentioning features or use of this software
22
 *    must display the following acknowledgment:
23
 *    "This product includes software developed by the pfSense Project
24
 *    for use in the pfSense® software distribution. (http://www.pfsense.org/).
25
 *
26
 * 4. The names "pfSense" and "pfSense Project" must not be used to
27
 *    endorse or promote products derived from this software without
28
 *    prior written permission. For written permission, please contact
29
 *    coreteam@pfsense.org.
30
 *
31
 * 5. Products derived from this software may not be called "pfSense"
32
 *    nor may "pfSense" appear in their names without prior written
33
 *    permission of the Electric Sheep Fencing, LLC.
34
 *
35
 * 6. Redistributions of any form whatsoever must retain the following
36
 *    acknowledgment:
37
 *
38
 * "This product includes software developed by the pfSense Project
39
 * for use in the pfSense software distribution (http://www.pfsense.org/).
40
 *
41
 * THIS SOFTWARE IS PROVIDED BY THE pfSense PROJECT ``AS IS'' AND ANY
42
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
44
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE pfSense PROJECT OR
45
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
46
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
47
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
48
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
50
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
51
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
52
 * OF THE POSSIBILITY OF SUCH DAMAGE.
53
 */
54

    
55
##|+PRIV
56
##|*IDENT=page-system-camanager
57
##|*NAME=System: CA Manager
58
##|*DESCR=Allow access to the 'System: CA Manager' page.
59
##|*MATCH=system_camanager.php*
60
##|-PRIV
61

    
62
require_once("guiconfig.inc");
63
require_once("certs.inc");
64

    
65
$ca_methods = array(
66
	"existing" => gettext("Import an existing Certificate Authority"),
67
	"internal" => gettext("Create an internal Certificate Authority"),
68
	"intermediate" => gettext("Create an intermediate Certificate Authority"));
69

    
70
$ca_keylens = array("512", "1024", "2048", "3072", "4096", "7680", "8192", "15360", "16384");
71
$openssl_digest_algs = array("sha1", "sha224", "sha256", "sha384", "sha512", "whirlpool");
72

    
73
if (is_numericint($_GET['id'])) {
74
	$id = $_GET['id'];
75
}
76
if (isset($_POST['id']) && is_numericint($_POST['id'])) {
77
	$id = $_POST['id'];
78
}
79

    
80
if (!is_array($config['ca'])) {
81
	$config['ca'] = array();
82
}
83

    
84
$a_ca =& $config['ca'];
85

    
86
if (!is_array($config['cert'])) {
87
	$config['cert'] = array();
88
}
89

    
90
$a_cert =& $config['cert'];
91

    
92
if (!is_array($config['crl'])) {
93
	$config['crl'] = array();
94
}
95

    
96
$a_crl =& $config['crl'];
97

    
98
$act = $_GET['act'];
99
if ($_POST['act']) {
100
	$act = $_POST['act'];
101
}
102

    
103
if ($act == "del") {
104

    
105
	if (!isset($a_ca[$id])) {
106
		pfSenseHeader("system_camanager.php");
107
		exit;
108
	}
109

    
110
	$index = count($a_cert) - 1;
111
	for (;$index >= 0; $index--) {
112
		if ($a_cert[$index]['caref'] == $a_ca[$id]['refid']) {
113
			unset($a_cert[$index]);
114
		}
115
	}
116

    
117
	$index = count($a_crl) - 1;
118
	for (;$index >= 0; $index--) {
119
		if ($a_crl[$index]['caref'] == $a_ca[$id]['refid']) {
120
			unset($a_crl[$index]);
121
		}
122
	}
123

    
124
	$name = $a_ca[$id]['descr'];
125
	unset($a_ca[$id]);
126
	write_config();
127
	$savemsg = sprintf(gettext("Certificate Authority %s and its CRLs (if any) successfully deleted."), htmlspecialchars($name));
128
	pfSenseHeader("system_camanager.php");
129
	exit;
130
}
131

    
132
if ($act == "edit") {
133
	if (!$a_ca[$id]) {
134
		pfSenseHeader("system_camanager.php");
135
		exit;
136
	}
137
	$pconfig['descr']  = $a_ca[$id]['descr'];
138
	$pconfig['refid']  = $a_ca[$id]['refid'];
139
	$pconfig['cert']   = base64_decode($a_ca[$id]['crt']);
140
	$pconfig['serial'] = $a_ca[$id]['serial'];
141
	if (!empty($a_ca[$id]['prv'])) {
142
		$pconfig['key'] = base64_decode($a_ca[$id]['prv']);
143
	}
144
}
145

    
146
if ($act == "new") {
147
	$pconfig['method'] = $_GET['method'];
148
	$pconfig['keylen'] = "2048";
149
	$pconfig['digest_alg'] = "sha256";
150
	$pconfig['lifetime'] = "3650";
151
	$pconfig['dn_commonname'] = "internal-ca";
152
}
153

    
154
if ($act == "exp") {
155

    
156
	if (!$a_ca[$id]) {
157
		pfSenseHeader("system_camanager.php");
158
		exit;
159
	}
160

    
161
	$exp_name = urlencode("{$a_ca[$id]['descr']}.crt");
162
	$exp_data = base64_decode($a_ca[$id]['crt']);
163
	$exp_size = strlen($exp_data);
164

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

    
172
if ($act == "expkey") {
173

    
174
	if (!$a_ca[$id]) {
175
		pfSenseHeader("system_camanager.php");
176
		exit;
177
	}
178

    
179
	$exp_name = urlencode("{$a_ca[$id]['descr']}.key");
180
	$exp_data = base64_decode($a_ca[$id]['prv']);
181
	$exp_size = strlen($exp_data);
182

    
183
	header("Content-Type: application/octet-stream");
184
	header("Content-Disposition: attachment; filename={$exp_name}");
185
	header("Content-Length: $exp_size");
186
	echo $exp_data;
187
	exit;
188
}
189

    
190
if ($_POST) {
191

    
192
	unset($input_errors);
193
	$input_errors = array();
194
	$pconfig = $_POST;
195

    
196
	/* input validation */
197
	if ($pconfig['method'] == "existing") {
198
		$reqdfields = explode(" ", "descr cert");
199
		$reqdfieldsn = array(
200
			gettext("Descriptive name"),
201
			gettext("Certificate data"));
202
		if ($_POST['cert'] && (!strstr($_POST['cert'], "BEGIN CERTIFICATE") || !strstr($_POST['cert'], "END CERTIFICATE"))) {
203
			$input_errors[] = gettext("This certificate does not appear to be valid.");
204
		}
205
		if ($_POST['key'] && strstr($_POST['key'], "ENCRYPTED")) {
206
			$input_errors[] = gettext("Encrypted private keys are not yet supported.");
207
		}
208
	}
209
	if ($pconfig['method'] == "internal") {
210
		$reqdfields = explode(" ",
211
			"descr keylen lifetime dn_country dn_state dn_city ".
212
			"dn_organization dn_email dn_commonname");
213
		$reqdfieldsn = array(
214
			gettext("Descriptive name"),
215
			gettext("Key length"),
216
			gettext("Lifetime"),
217
			gettext("Distinguished name Country Code"),
218
			gettext("Distinguished name State or Province"),
219
			gettext("Distinguished name City"),
220
			gettext("Distinguished name Organization"),
221
			gettext("Distinguished name Email Address"),
222
			gettext("Distinguished name Common Name"));
223
	}
224
	if ($pconfig['method'] == "intermediate") {
225
		$reqdfields = explode(" ",
226
			"descr caref keylen lifetime dn_country dn_state dn_city ".
227
			"dn_organization dn_email dn_commonname");
228
		$reqdfieldsn = array(
229
			gettext("Descriptive name"),
230
			gettext("Signing Certificate Authority"),
231
			gettext("Key length"),
232
			gettext("Lifetime"),
233
			gettext("Distinguished name Country Code"),
234
			gettext("Distinguished name State or Province"),
235
			gettext("Distinguished name City"),
236
			gettext("Distinguished name Organization"),
237
			gettext("Distinguished name Email Address"),
238
			gettext("Distinguished name Common Name"));
239
	}
240

    
241
	do_input_validation($_POST, $reqdfields, $reqdfieldsn, $input_errors);
242
	if ($pconfig['method'] != "existing") {
243
		/* Make sure we do not have invalid characters in the fields for the certificate */
244
		if (preg_match("/[\?\>\<\&\/\\\"\']/", $_POST['descr'])) {
245
			array_push($input_errors, gettext("The field 'Descriptive Name' contains invalid characters."));
246
		}
247

    
248
		for ($i = 0; $i < count($reqdfields); $i++) {
249
			if ($reqdfields[$i] == 'dn_email') {
250
				if (preg_match("/[\!\#\$\%\^\(\)\~\?\>\<\&\/\\\,\"\']/", $_POST["dn_email"])) {
251
					array_push($input_errors, gettext("The field 'Distinguished name Email Address' contains invalid characters."));
252
				}
253
			} else if ($reqdfields[$i] == 'dn_commonname') {
254
				if (preg_match("/[\!\@\#\$\%\^\(\)\~\?\>\<\&\/\\\,\"\']/", $_POST["dn_commonname"])) {
255
					array_push($input_errors, gettext("The field 'Distinguished name Common Name' contains invalid characters."));
256
				}
257
			} else if (($reqdfields[$i] != "descr") && preg_match("/[\!\@\#\$\%\^\(\)\~\?\>\<\&\/\\\,\.\"\']/", $_POST["$reqdfields[$i]"])) {
258
				array_push($input_errors, sprintf(gettext("The field '%s' contains invalid characters."), $reqdfieldsn[$i]));
259
			}
260
		}
261
		if (!in_array($_POST["keylen"], $ca_keylens)) {
262
			array_push($input_errors, gettext("Please select a valid Key Length."));
263
		}
264
		if (!in_array($_POST["digest_alg"], $openssl_digest_algs)) {
265
			array_push($input_errors, gettext("Please select a valid Digest Algorithm."));
266
		}
267
	}
268

    
269
	/* save modifications */
270
	if (!$input_errors) {
271
		$ca = array();
272
		if (!isset($pconfig['refid']) || empty($pconfig['refid'])) {
273
			$ca['refid'] = uniqid();
274
		} else {
275
			$ca['refid'] = $pconfig['refid'];
276
		}
277

    
278
		if (isset($id) && $a_ca[$id]) {
279
			$ca = $a_ca[$id];
280
		}
281

    
282
		$ca['descr'] = $pconfig['descr'];
283

    
284
		if ($act == "edit") {
285
			$ca['descr']  = $pconfig['descr'];
286
			$ca['refid']  = $pconfig['refid'];
287
			$ca['serial'] = $pconfig['serial'];
288
			$ca['crt']	  = base64_encode($pconfig['cert']);
289
			if (!empty($pconfig['key'])) {
290
				$ca['prv']	  = base64_encode($pconfig['key']);
291
			}
292
		} else {
293
			$old_err_level = error_reporting(0); /* otherwise openssl_ functions throw warnings directly to a page screwing menu tab */
294
			if ($pconfig['method'] == "existing") {
295
				ca_import($ca, $pconfig['cert'], $pconfig['key'], $pconfig['serial']);
296
			} else if ($pconfig['method'] == "internal") {
297
				$dn = array(
298
					'countryName' => $pconfig['dn_country'],
299
					'stateOrProvinceName' => $pconfig['dn_state'],
300
					'localityName' => $pconfig['dn_city'],
301
					'organizationName' => $pconfig['dn_organization'],
302
					'emailAddress' => $pconfig['dn_email'],
303
					'commonName' => $pconfig['dn_commonname']);
304
				if (!empty($pconfig['dn_organizationalunit'])) {
305
					$dn['organizationalUnitName'] = $pconfig['dn_organizationalunit'];
306
				}
307
				if (!ca_create($ca, $pconfig['keylen'], $pconfig['lifetime'], $dn, $pconfig['digest_alg'])) {
308
					while ($ssl_err = openssl_error_string()) {
309
						$input_errors = array();
310
						array_push($input_errors, "openssl library returns: " . $ssl_err);
311
					}
312
				}
313
			} else if ($pconfig['method'] == "intermediate") {
314
				$dn = array(
315
					'countryName' => $pconfig['dn_country'],
316
					'stateOrProvinceName' => $pconfig['dn_state'],
317
					'localityName' => $pconfig['dn_city'],
318
					'organizationName' => $pconfig['dn_organization'],
319
					'emailAddress' => $pconfig['dn_email'],
320
					'commonName' => $pconfig['dn_commonname']);
321
				if (!empty($pconfig['dn_organizationalunit'])) {
322
					$dn['organizationalUnitName'] = $pconfig['dn_organizationalunit'];
323
				}
324
				if (!ca_inter_create($ca, $pconfig['keylen'], $pconfig['lifetime'], $dn, $pconfig['caref'], $pconfig['digest_alg'])) {
325
					while ($ssl_err = openssl_error_string()) {
326
						$input_errors = array();
327
						array_push($input_errors, "openssl library returns: " . $ssl_err);
328
					}
329
				}
330
			}
331
			error_reporting($old_err_level);
332
		}
333

    
334
		if (isset($id) && $a_ca[$id]) {
335
			$a_ca[$id] = $ca;
336
		} else {
337
			$a_ca[] = $ca;
338
		}
339

    
340
		if (!$input_errors) {
341
			write_config();
342
		}
343

    
344
		pfSenseHeader("system_camanager.php");
345
	}
346
}
347

    
348
$pgtitle = array(gettext("System"), gettext("Certificate Manager"), gettext("CAs"));
349

    
350
if ($act == "new" || $act == "edit" || $act == gettext("Save") || $input_errors) {
351
	$pgtitle[] = gettext('Edit');
352
}
353
include("head.inc");
354

    
355
if ($input_errors) {
356
	print_input_errors($input_errors);
357
}
358

    
359
if ($savemsg) {
360
	print_info_box($savemsg, 'success');
361
}
362

    
363
// Load valid country codes
364
$dn_cc = array();
365
if (file_exists("/etc/ca_countries")) {
366
	$dn_cc_file=file("/etc/ca_countries");
367
	foreach ($dn_cc_file as $line) {
368
		if (preg_match('/^(\S*)\s(.*)$/', $line, $matches)) {
369
			$dn_cc[$matches[1]] = $matches[1];
370
		}
371
	}
372
}
373

    
374
$tab_array = array();
375
$tab_array[] = array(gettext("CAs"), true, "system_camanager.php");
376
$tab_array[] = array(gettext("Certificates"), false, "system_certmanager.php");
377
$tab_array[] = array(gettext("Certificate Revocation"), false, "system_crlmanager.php");
378
display_top_tabs($tab_array);
379

    
380
if (!($act == "new" || $act == "edit" || $act == gettext("Save") || $input_errors)) {
381
?>
382
<div class="panel panel-default">
383
	<div class="panel-heading"><h2 class="panel-title"><?=gettext('Certificate Authorities')?></h2></div>
384
	<div class="panel-body">
385
		<div class="table-responsive">
386
		<table class="table table-striped table-hover table-rowdblclickedit">
387
			<thead>
388
				<tr>
389
					<th><?=gettext("Name")?></th>
390
					<th><?=gettext("Internal")?></th>
391
					<th><?=gettext("Issuer")?></th>
392
					<th><?=gettext("Certificates")?></th>
393
					<th><?=gettext("Distinguished Name")?></th>
394
					<th><?=gettext("Actions")?></th>
395
				</tr>
396
			</thead>
397
			<tbody>
398
<?php
399
foreach ($a_ca as $i => $ca):
400
	$name = htmlspecialchars($ca['descr']);
401
	$subj = cert_get_subject($ca['crt']);
402
	$issuer = cert_get_issuer($ca['crt']);
403
	list($startdate, $enddate) = cert_get_dates($ca['crt']);
404
	if ($subj == $issuer) {
405
		$issuer_name = gettext("self-signed");
406
	} else {
407
		$issuer_name = gettext("external");
408
	}
409
	$subj = htmlspecialchars($subj);
410
	$issuer = htmlspecialchars($issuer);
411
	$certcount = 0;
412

    
413
	$issuer_ca = lookup_ca($ca['caref']);
414
	if ($issuer_ca) {
415
		$issuer_name = $issuer_ca['descr'];
416
	}
417

    
418
	foreach ($a_cert as $cert) {
419
		if ($cert['caref'] == $ca['refid']) {
420
			$certcount++;
421
		}
422
	}
423

    
424
	foreach ($a_ca as $cert) {
425
		if ($cert['caref'] == $ca['refid']) {
426
			$certcount++;
427
		}
428
	}
429
?>
430
				<tr>
431
					<td><?=$name?></td>
432
					<td><i class="fa fa-<?= (!empty($ca['prv'])) ? "check" : "times" ; ?>"></i></td>
433
					<td><i><?=$issuer_name?></i></td>
434
					<td><?=$certcount?></td>
435
					<td>
436
						<?=$subj?>
437
						<br />
438
						<small>
439
							<?=gettext("Valid From")?>: <b><?=$startdate ?></b><br /><?=gettext("Valid Until")?>: <b><?=$enddate ?></b>
440
						</small>
441
					</td>
442
					<td>
443
						<a class="fa fa-pencil"	title="<?=gettext("Edit CA")?>"	href="system_camanager.php?act=edit&amp;id=<?=$i?>"></a>
444
						<a class="fa fa-certificate"	title="<?=gettext("Export CA")?>"	href="system_camanager.php?act=exp&amp;id=<?=$i?>"></a>
445
					<?php if ($ca['prv']): ?>
446
						<a class="fa fa-key"	title="<?=gettext("Export key")?>"	href="system_camanager.php?act=expkey&amp;id=<?=$i?>"></a>
447
					<?php endif?>
448
						<a class="fa fa-trash" 	title="<?=gettext("Delete CA")?>"	href="system_camanager.php?act=del&amp;id=<?=$i?>"></a>
449
					</td>
450
				</tr>
451
<?php endforeach; ?>
452
			</tbody>
453
		</table>
454
		</div>
455
	</div>
456
</div>
457

    
458
<nav class="action-buttons">
459
	<a href="?act=new" class="btn btn-success btn-sm">
460
		<i class="fa fa-plus icon-embed-btn"></i>
461
		<?=gettext("Add")?>
462
	</a>
463
</nav>
464
<?php
465
	include("foot.inc");
466
	exit;
467
}
468

    
469
$form = new Form;
470
//$form->setAction('system_camanager.php?act=edit');
471
if (isset($id) && $a_ca[$id]) {
472
	$form->addGlobal(new Form_Input(
473
		'id',
474
		null,
475
		'hidden',
476
		$id
477
	));
478
}
479

    
480
if ($act == "edit") {
481
	$form->addGlobal(new Form_Input(
482
		'refid',
483
		null,
484
		'hidden',
485
		$pconfig['refid']
486
	));
487
}
488

    
489
$section = new Form_Section('Create / Edit CA');
490

    
491
$section->addInput(new Form_Input(
492
	'descr',
493
	'Descriptive name',
494
	'text',
495
	$pconfig['descr']
496
));
497

    
498
if (!isset($id) || $act == "edit") {
499
	$section->addInput(new Form_Select(
500
		'method',
501
		'Method',
502
		$pconfig['method'],
503
		$ca_methods
504
	))->toggles();
505
}
506

    
507
$form->add($section);
508

    
509
$section = new Form_Section('Existing Certificate Authority');
510
$section->addClass('toggle-existing collapse');
511

    
512
$section->addInput(new Form_Textarea(
513
	'cert',
514
	'Certificate data',
515
	$pconfig['cert']
516
))->setHelp('Paste a certificate in X.509 PEM format here.');
517

    
518
$section->addInput(new Form_Textarea(
519
	'key',
520
	'Certificate Private Key (optional)',
521
	$pconfig['key']
522
))->setHelp('Paste the private key for the above certificate here. This is '.
523
	'optional in most cases, but is required when generating a '.
524
	'Certificate Revocation List (CRL).');
525

    
526
$section->addInput(new Form_Input(
527
	'serial',
528
	'Serial for next certificate',
529
	'number',
530
	$pconfig['serial']
531
))->setHelp('Enter a decimal number to be used as the serial number for the next '.
532
	'certificate to be created using this CA.');
533

    
534
$form->add($section);
535

    
536
$section = new Form_Section('Internal Certificate Authority');
537
$section->addClass('toggle-internal', 'toggle-intermediate', 'collapse');
538

    
539
$allCas = array();
540
foreach ($a_ca as $ca) {
541
	if (!$ca['prv']) {
542
			continue;
543
	}
544

    
545
	$allCas[ $ca['refid'] ] = $ca['descr'];
546
}
547

    
548
$group = new Form_Group('Signing Certificate Authority');
549
$group->addClass('toggle-intermediate', 'collapse');
550
$group->add(new Form_Select(
551
	'caref',
552
	null,
553
	$pconfig['caref'],
554
	$allCas
555
));
556
$section->add($group);
557

    
558
$section->addInput(new Form_Select(
559
	'keylen',
560
	'Key length (bits)',
561
	$pconfig['keylen'],
562
	array_combine($ca_keylens, $ca_keylens)
563
));
564

    
565
$section->addInput(new Form_Select(
566
	'digest_alg',
567
	'Digest Algorithm',
568
	$pconfig['digest_alg'],
569
	array_combine($openssl_digest_algs, $openssl_digest_algs)
570
))->setHelp('NOTE: It is recommended to use an algorithm stronger than SHA1 '.
571
	'when possible.');
572

    
573
$section->addInput(new Form_Input(
574
	'lifetime',
575
	'Lifetime (days)',
576
	'number',
577
	$pconfig['lifetime']
578
));
579

    
580
$section->addInput(new Form_Select(
581
	'dn_country',
582
	'Country Code',
583
	$pconfig['dn_country'],
584
	$dn_cc
585
));
586

    
587
$section->addInput(new Form_Input(
588
	'dn_state',
589
	'State or Province',
590
	'text',
591
	$pconfig['dn_state'],
592
	['placeholder' => 'e.g. Texas']
593
));
594

    
595
$section->addInput(new Form_Input(
596
	'dn_city',
597
	'City',
598
	'text',
599
	$pconfig['dn_city'],
600
	['placeholder' => 'e.g. Austin']
601
));
602

    
603
$section->addInput(new Form_Input(
604
	'dn_organization',
605
	'Organization',
606
	'text',
607
	$pconfig['dn_organization'],
608
	['placeholder' => 'e.g. My Company Inc']
609
));
610

    
611
$section->addInput(new Form_Input(
612
	'dn_organizationalunit',
613
	'Organizational Unit',
614
	'text',
615
	$pconfig['dn_organizationalunit'],
616
	['placeholder' => 'e.g. My Department Name (optional)']
617
));
618

    
619
$section->addInput(new Form_Input(
620
	'dn_email',
621
	'Email Address',
622
	'email',
623
	$pconfig['dn_email'],
624
	['placeholder' => 'e.g. admin@mycompany.com']
625
));
626

    
627
$section->addInput(new Form_Input(
628
	'dn_commonname',
629
	'Common Name',
630
	'text',
631
	$pconfig['dn_commonname'],
632
	['placeholder' => 'e.g. internal-ca']
633
));
634

    
635
$form->add($section);
636

    
637
print $form;
638

    
639
$internal_ca_count = 0;
640
foreach ($a_ca as $ca) {
641
	if ($ca['prv']) {
642
		$internal_ca_count++;
643
	}
644
}
645

    
646
include('foot.inc');
647
?>
(194-194/227)