Project

General

Profile

Download (18.2 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-2018 Rubicon Communications, LLC (Netgate)
7
 * Copyright (c) 2008 Shrew Soft Inc
8
 * All rights reserved.
9
 *
10
 * Licensed under the Apache License, Version 2.0 (the "License");
11
 * you may not use this file except in compliance with the License.
12
 * You may obtain a copy of the License at
13
 *
14
 * http://www.apache.org/licenses/LICENSE-2.0
15
 *
16
 * Unless required by applicable law or agreed to in writing, software
17
 * distributed under the License is distributed on an "AS IS" BASIS,
18
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19
 * See the License for the specific language governing permissions and
20
 * limitations under the License.
21
 */
22

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

    
30
require_once("guiconfig.inc");
31
require_once("certs.inc");
32
require_once("pfsense-utils.inc");
33

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

    
39
$ca_keylens = array("512", "1024", "2048", "3072", "4096", "7680", "8192", "15360", "16384");
40
global $openssl_digest_algs;
41

    
42
if (isset($_REQUEST['id']) && is_numericint($_REQUEST['id'])) {
43
	$id = $_REQUEST['id'];
44
}
45

    
46
if (!is_array($config['ca'])) {
47
	$config['ca'] = array();
48
}
49

    
50
$a_ca =& $config['ca'];
51

    
52
if (!is_array($config['cert'])) {
53
	$config['cert'] = array();
54
}
55

    
56
$a_cert =& $config['cert'];
57

    
58
if (!is_array($config['crl'])) {
59
	$config['crl'] = array();
60
}
61

    
62
$a_crl =& $config['crl'];
63

    
64
if ($_REQUEST['act']) {
65
	$act = $_REQUEST['act'];
66
}
67

    
68
if ($_POST['act'] == "del") {
69

    
70
	if (!isset($a_ca[$id])) {
71
		pfSenseHeader("system_camanager.php");
72
		exit;
73
	}
74

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
220
	do_input_validation($_POST, $reqdfields, $reqdfieldsn, $input_errors);
221
	if ($pconfig['method'] != "existing") {
222
		/* Make sure we do not have invalid characters in the fields for the certificate */
223
		if (preg_match("/[\?\>\<\&\/\\\"\']/", $_POST['descr'])) {
224
			array_push($input_errors, gettext("The field 'Descriptive Name' contains invalid characters."));
225
		}
226

    
227
		for ($i = 0; $i < count($reqdfields); $i++) {
228
			if ($reqdfields[$i] == 'dn_email') {
229
				if (preg_match("/[\!\#\$\%\^\(\)\~\?\>\<\&\/\\\,\"\']/", $_POST["dn_email"])) {
230
					array_push($input_errors, gettext("The field 'Distinguished name Email Address' contains invalid characters."));
231
				}
232
			}
233
		}
234
		if (!in_array($_POST["keylen"], $ca_keylens)) {
235
			array_push($input_errors, gettext("Please select a valid Key Length."));
236
		}
237
		if (!in_array($_POST["digest_alg"], $openssl_digest_algs)) {
238
			array_push($input_errors, gettext("Please select a valid Digest Algorithm."));
239
		}
240
	}
241

    
242
	/* save modifications */
243
	if (!$input_errors) {
244
		$ca = array();
245
		if (!isset($pconfig['refid']) || empty($pconfig['refid'])) {
246
			$ca['refid'] = uniqid();
247
		} else {
248
			$ca['refid'] = $pconfig['refid'];
249
		}
250

    
251
		if (isset($id) && $a_ca[$id]) {
252
			$ca = $a_ca[$id];
253
		}
254

    
255
		$ca['descr'] = $pconfig['descr'];
256

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

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

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

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

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

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

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

    
341
// Load valid country codes
342
$dn_cc = array();
343
if (file_exists("/etc/ca_countries")) {
344
	$dn_cc_file=file("/etc/ca_countries");
345
	foreach ($dn_cc_file as $line) {
346
		if (preg_match('/^(\S*)\s(.*)$/', $line, $matches)) {
347
			$dn_cc[$matches[1]] = $matches[1];
348
		}
349
	}
350
}
351

    
352
$tab_array = array();
353
$tab_array[] = array(gettext("CAs"), true, "system_camanager.php");
354
$tab_array[] = array(gettext("Certificates"), false, "system_certmanager.php");
355
$tab_array[] = array(gettext("Certificate Revocation"), false, "system_crlmanager.php");
356
display_top_tabs($tab_array);
357

    
358
if (!($act == "new" || $act == "edit" || $act == gettext("Save") || $input_errors)) {
359
?>
360
<div class="panel panel-default">
361
	<div class="panel-heading"><h2 class="panel-title"><?=gettext('Certificate Authorities')?></h2></div>
362
	<div class="panel-body">
363
		<div class="table-responsive">
364
		<table class="table table-striped table-hover table-rowdblclickedit">
365
			<thead>
366
				<tr>
367
					<th><?=gettext("Name")?></th>
368
					<th><?=gettext("Internal")?></th>
369
					<th><?=gettext("Issuer")?></th>
370
					<th><?=gettext("Certificates")?></th>
371
					<th><?=gettext("Distinguished Name")?></th>
372
					<th><?=gettext("In Use")?></th>
373
					<th><?=gettext("Actions")?></th>
374
				</tr>
375
			</thead>
376
			<tbody>
377
<?php
378
$pluginparams = array();
379
$pluginparams['type'] = 'certificates';
380
$pluginparams['event'] = 'used_ca';
381
$certificates_used_by_packages = pkg_call_plugins('plugin_certificates', $pluginparams);
382

    
383
foreach ($a_ca as $i => $ca):
384
	$name = htmlspecialchars($ca['descr']);
385
	$subj = cert_get_subject($ca['crt']);
386
	$issuer = cert_get_issuer($ca['crt']);
387
	list($startdate, $enddate) = cert_get_dates($ca['crt']);
388
	if ($subj == $issuer) {
389
		$issuer_name = gettext("self-signed");
390
	} else {
391
		$issuer_name = gettext("external");
392
	}
393
	$subj = htmlspecialchars(cert_escape_x509_chars($subj, true));
394
	$issuer = htmlspecialchars($issuer);
395
	$certcount = 0;
396

    
397
	$issuer_ca = lookup_ca($ca['caref']);
398
	if ($issuer_ca) {
399
		$issuer_name = $issuer_ca['descr'];
400
	}
401

    
402
	foreach ($a_cert as $cert) {
403
		if ($cert['caref'] == $ca['refid']) {
404
			$certcount++;
405
		}
406
	}
407

    
408
	foreach ($a_ca as $cert) {
409
		if ($cert['caref'] == $ca['refid']) {
410
			$certcount++;
411
		}
412
	}
413
?>
414
				<tr>
415
					<td><?=$name?></td>
416
					<td><i class="fa fa-<?= (!empty($ca['prv'])) ? "check" : "times" ; ?>"></i></td>
417
					<td><i><?=$issuer_name?></i></td>
418
					<td><?=$certcount?></td>
419
					<td>
420
						<?=$subj?>
421
						<br />
422
						<small>
423
							<?=gettext("Valid From")?>: <b><?=$startdate ?></b><br /><?=gettext("Valid Until")?>: <b><?=$enddate ?></b>
424
						</small>
425
					</td>
426
					<td class="text-nowrap">
427
						<?php if (is_openvpn_server_ca($ca['refid'])): ?>
428
							<?=gettext("OpenVPN Server")?><br/>
429
						<?php endif?>
430
						<?php if (is_openvpn_client_ca($ca['refid'])): ?>
431
							<?=gettext("OpenVPN Client")?><br/>
432
						<?php endif?>
433
						<?php if (is_ipsec_peer_ca($ca['refid'])): ?>
434
							<?=gettext("IPsec Tunnel")?><br/>
435
						<?php endif?>
436
						<?php if (is_ldap_peer_ca($ca['refid'])): ?>
437
							<?=gettext("LDAP Server")?>
438
						<?php endif?>
439
						<?php echo cert_usedby_description($ca['refid'], $certificates_used_by_packages); ?>
440
					</td>
441
					<td class="text-nowrap">
442
						<a class="fa fa-pencil"	title="<?=gettext("Edit CA")?>"	href="system_camanager.php?act=edit&amp;id=<?=$i?>"></a>
443
						<a class="fa fa-certificate"	title="<?=gettext("Export CA")?>"	href="system_camanager.php?act=exp&amp;id=<?=$i?>"></a>
444
					<?php if ($ca['prv']): ?>
445
						<a class="fa fa-key"	title="<?=gettext("Export key")?>"	href="system_camanager.php?act=expkey&amp;id=<?=$i?>"></a>
446
					<?php endif?>
447
					<?php if (!ca_in_use($ca['refid'])): ?>
448
						<a class="fa fa-trash" 	title="<?=gettext("Delete CA and its CRLs")?>"	href="system_camanager.php?act=del&amp;id=<?=$i?>" usepost ></a>
449
					<?php endif?>
450
					</td>
451
				</tr>
452
<?php endforeach; ?>
453
			</tbody>
454
		</table>
455
		</div>
456
	</div>
457
</div>
458

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
638
print $form;
639

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

    
647
include('foot.inc');
648
?>
(198-198/232)