Project

General

Profile

Download (18.4 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 Rubicon Communications, LLC (Netgate)
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
global $openssl_digest_algs;
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
					$input_errors = array();
309
					while ($ssl_err = openssl_error_string()) {
310
						if (strpos($ssl_err, 'NCONF_get_string:no value') === false) {
311
							array_push($input_errors, "openssl library returns: " . $ssl_err);
312
						}
313
					}
314
				}
315
			} else if ($pconfig['method'] == "intermediate") {
316
				$dn = array(
317
					'countryName' => $pconfig['dn_country'],
318
					'stateOrProvinceName' => $pconfig['dn_state'],
319
					'localityName' => $pconfig['dn_city'],
320
					'organizationName' => $pconfig['dn_organization'],
321
					'emailAddress' => $pconfig['dn_email'],
322
					'commonName' => $pconfig['dn_commonname']);
323
				if (!empty($pconfig['dn_organizationalunit'])) {
324
					$dn['organizationalUnitName'] = $pconfig['dn_organizationalunit'];
325
				}
326
				if (!ca_inter_create($ca, $pconfig['keylen'], $pconfig['lifetime'], $dn, $pconfig['caref'], $pconfig['digest_alg'])) {
327
					$input_errors = array();
328
					while ($ssl_err = openssl_error_string()) {
329
						if (strpos($ssl_err, 'NCONF_get_string:no value') === false) {
330
							array_push($input_errors, "openssl library returns: " . $ssl_err);
331
						}
332
					}
333
				}
334
			}
335
			error_reporting($old_err_level);
336
		}
337

    
338
		if (isset($id) && $a_ca[$id]) {
339
			$a_ca[$id] = $ca;
340
		} else {
341
			$a_ca[] = $ca;
342
		}
343

    
344
		if (!$input_errors) {
345
			write_config();
346
			pfSenseHeader("system_camanager.php");
347
		}
348
	}
349
}
350

    
351
$pgtitle = array(gettext("System"), gettext("Certificate Manager"), gettext("CAs"));
352
$pglinks = array("", "system_camanager.php", "system_camanager.php");
353

    
354
if ($act == "new" || $act == "edit" || $act == gettext("Save") || $input_errors) {
355
	$pgtitle[] = gettext('Edit');
356
	$pglinks[] = "@self";
357
}
358
include("head.inc");
359

    
360
if ($input_errors) {
361
	print_input_errors($input_errors);
362
}
363

    
364
if ($savemsg) {
365
	print_info_box($savemsg, 'success');
366
}
367

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

    
379
$tab_array = array();
380
$tab_array[] = array(gettext("CAs"), true, "system_camanager.php");
381
$tab_array[] = array(gettext("Certificates"), false, "system_certmanager.php");
382
$tab_array[] = array(gettext("Certificate Revocation"), false, "system_crlmanager.php");
383
display_top_tabs($tab_array);
384

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

    
418
	$issuer_ca = lookup_ca($ca['caref']);
419
	if ($issuer_ca) {
420
		$issuer_name = $issuer_ca['descr'];
421
	}
422

    
423
	foreach ($a_cert as $cert) {
424
		if ($cert['caref'] == $ca['refid']) {
425
			$certcount++;
426
		}
427
	}
428

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

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

    
474
$form = new Form;
475
//$form->setAction('system_camanager.php?act=edit');
476
if (isset($id) && $a_ca[$id]) {
477
	$form->addGlobal(new Form_Input(
478
		'id',
479
		null,
480
		'hidden',
481
		$id
482
	));
483
}
484

    
485
if ($act == "edit") {
486
	$form->addGlobal(new Form_Input(
487
		'refid',
488
		null,
489
		'hidden',
490
		$pconfig['refid']
491
	));
492
}
493

    
494
$section = new Form_Section('Create / Edit CA');
495

    
496
$section->addInput(new Form_Input(
497
	'descr',
498
	'*Descriptive name',
499
	'text',
500
	$pconfig['descr']
501
));
502

    
503
if (!isset($id) || $act == "edit") {
504
	$section->addInput(new Form_Select(
505
		'method',
506
		'*Method',
507
		$pconfig['method'],
508
		$ca_methods
509
	))->toggles();
510
}
511

    
512
$form->add($section);
513

    
514
$section = new Form_Section('Existing Certificate Authority');
515
$section->addClass('toggle-existing collapse');
516

    
517
$section->addInput(new Form_Textarea(
518
	'cert',
519
	'*Certificate data',
520
	$pconfig['cert']
521
))->setHelp('Paste a certificate in X.509 PEM format here.');
522

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

    
531
$section->addInput(new Form_Input(
532
	'serial',
533
	'Serial for next certificate',
534
	'number',
535
	$pconfig['serial']
536
))->setHelp('Enter a decimal number to be used as the serial number for the next '.
537
	'certificate to be created using this CA.');
538

    
539
$form->add($section);
540

    
541
$section = new Form_Section('Internal Certificate Authority');
542
$section->addClass('toggle-internal', 'toggle-intermediate', 'collapse');
543

    
544
$allCas = array();
545
foreach ($a_ca as $ca) {
546
	if (!$ca['prv']) {
547
			continue;
548
	}
549

    
550
	$allCas[ $ca['refid'] ] = $ca['descr'];
551
}
552

    
553
$group = new Form_Group('*Signing Certificate Authority');
554
$group->addClass('toggle-intermediate', 'collapse');
555
$group->add(new Form_Select(
556
	'caref',
557
	null,
558
	$pconfig['caref'],
559
	$allCas
560
));
561
$section->add($group);
562

    
563
$section->addInput(new Form_Select(
564
	'keylen',
565
	'*Key length (bits)',
566
	$pconfig['keylen'],
567
	array_combine($ca_keylens, $ca_keylens)
568
));
569

    
570
$section->addInput(new Form_Select(
571
	'digest_alg',
572
	'*Digest Algorithm',
573
	$pconfig['digest_alg'],
574
	array_combine($openssl_digest_algs, $openssl_digest_algs)
575
))->setHelp('NOTE: It is recommended to use an algorithm stronger than SHA1 '.
576
	'when possible.');
577

    
578
$section->addInput(new Form_Input(
579
	'lifetime',
580
	'*Lifetime (days)',
581
	'number',
582
	$pconfig['lifetime']
583
));
584

    
585
$section->addInput(new Form_Select(
586
	'dn_country',
587
	'*Country Code',
588
	$pconfig['dn_country'],
589
	$dn_cc
590
));
591

    
592
$section->addInput(new Form_Input(
593
	'dn_state',
594
	'*State or Province',
595
	'text',
596
	$pconfig['dn_state'],
597
	['placeholder' => 'e.g. Texas']
598
));
599

    
600
$section->addInput(new Form_Input(
601
	'dn_city',
602
	'*City',
603
	'text',
604
	$pconfig['dn_city'],
605
	['placeholder' => 'e.g. Austin']
606
));
607

    
608
$section->addInput(new Form_Input(
609
	'dn_organization',
610
	'*Organization',
611
	'text',
612
	$pconfig['dn_organization'],
613
	['placeholder' => 'e.g. My Company Inc']
614
));
615

    
616
$section->addInput(new Form_Input(
617
	'dn_organizationalunit',
618
	'Organizational Unit',
619
	'text',
620
	$pconfig['dn_organizationalunit'],
621
	['placeholder' => 'e.g. My Department Name (optional)']
622
));
623

    
624
$section->addInput(new Form_Input(
625
	'dn_email',
626
	'*Email Address',
627
	'email',
628
	$pconfig['dn_email'],
629
	['placeholder' => 'e.g. admin@mycompany.com']
630
));
631

    
632
$section->addInput(new Form_Input(
633
	'dn_commonname',
634
	'*Common Name',
635
	'text',
636
	$pconfig['dn_commonname'],
637
	['placeholder' => 'e.g. internal-ca']
638
));
639

    
640
$form->add($section);
641

    
642
print $form;
643

    
644
$internal_ca_count = 0;
645
foreach ($a_ca as $ca) {
646
	if ($ca['prv']) {
647
		$internal_ca_count++;
648
	}
649
}
650

    
651
include('foot.inc');
652
?>
(192-192/225)