Project

General

Profile

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

    
24
##|+PRIV
25
##|*IDENT=page-system-crlmanager
26
##|*NAME=System: CRL Manager
27
##|*DESCR=Allow access to the 'System: CRL Manager' page.
28
##|*MATCH=system_crlmanager.php*
29
##|-PRIV
30

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

    
37
$max_lifetime = crl_get_max_lifetime();
38
$default_lifetime = min(730, $max_lifetime);
39

    
40
global $openssl_crl_status;
41

    
42
$crl_methods = array(
43
	"internal" => gettext("Create an internal Certificate Revocation List"),
44
	"existing" => gettext("Import an existing Certificate Revocation List"));
45

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

    
50
config_init_path('ca');
51
config_init_path('cert');
52
config_init_path('crl');
53

    
54
/* Clean up blank entries missing a reference ID */
55
foreach (config_get_path('crl', []) as $cid => $acrl) {
56
	if (!isset($acrl['refid'])) {
57
		config_del_path("crl/{$cid}");
58
	}
59
}
60

    
61
$act = $_REQUEST['act'];
62

    
63
$cacert_list = array();
64

    
65
if (!empty($id)) {
66
	$crl_item_config = lookup_crl($id);
67
	$thiscrl = &$crl_item_config['item'];
68
}
69

    
70
/* Actions other than 'new' require a CRL to act upon.
71
 * 'del' action must be submitted via POST. */
72
if ((!empty($act) &&
73
    ($act != 'new') &&
74
    !$thiscrl) ||
75
    (($act == 'del') && empty($_POST))) {
76
	pfSenseHeader("system_camanager.php");
77
	$act="";
78
	$savemsg = gettext("Invalid CRL reference.");
79
	$class = "danger";
80
}
81

    
82
switch ($act) {
83
	case 'del':
84
		$name = htmlspecialchars($thiscrl['descr']);
85
		if (crl_in_use($id)) {
86
			$savemsg = sprintf(gettext("Certificate Revocation List %s is in use and cannot be deleted."), $name);
87
			$class = "danger";
88
		} else {
89
			foreach (config_get_path('crl', []) as $cid => $acrl) {
90
				if ($acrl['refid'] == $thiscrl['refid']) {
91
					config_del_path("crl/{$cid}");
92
				}
93
			}
94
			write_config("Deleted CRL {$name}.");
95
			$savemsg = sprintf(gettext("Certificate Revocation List %s successfully deleted."), $name);
96
			$class = "success";
97
		}
98
		break;
99
	case 'new':
100
		$pconfig['method'] = $_REQUEST['method'];
101
		$pconfig['caref'] = $_REQUEST['caref'];
102
		$pconfig['lifetime'] = $default_lifetime;
103
		$pconfig['serial'] = "0";
104
		$crlca = lookup_ca($pconfig['caref']);
105
		$crlca = $crlca['item'];
106
		if (!$crlca) {
107
			$input_errors[] = gettext('Invalid CA');
108
			unset($act);
109
		}
110
		break;
111
	case 'addcert':
112
		unset($input_errors);
113
		$pconfig = $_REQUEST;
114

    
115
		/* input validation */
116
		$reqdfields = explode(" ", "descr id");
117
		$reqdfieldsn = array(
118
			gettext("Descriptive name"),
119
			gettext("CRL ID"));
120

    
121
		do_input_validation($_POST, $reqdfields, $reqdfieldsn, $input_errors);
122

    
123
		if (preg_match("/[\?\>\<\&\/\\\"\']/", $pconfig['descr'])) {
124
			array_push($input_errors, "The field 'Descriptive Name' contains invalid characters.");
125
		}
126
		if ($pconfig['lifetime'] > $max_lifetime) {
127
			$input_errors[] = gettext("Lifetime is longer than the maximum allowed value. Use a shorter lifetime.");
128
		}
129
		if ((strlen($pconfig['serial']) > 0) && !cert_validate_serial($pconfig['serial'])) {
130
			$input_errors[] = gettext("Please enter a valid integer serial number.");
131
		}
132

    
133
		$revoke_list = array();
134
		if (!$pconfig['crlref']) {
135
			pfSenseHeader("system_crlmanager.php");
136
			exit;
137
		}
138
		$crl_item_config = lookup_crl($pconfig['crlref']);
139
		$crl = &$crl_item_config['item'];
140

    
141
		if (!is_array($pconfig['certref'])) {
142
			$pconfig['certref'] = array();
143
		}
144
		if (!is_crl_internal($crl)) {
145
			$input_errors[] = gettext("Cannot revoke certificates for an imported/external CRL.");
146
		}
147
		if (!empty($pconfig['revokeserial'])) {
148
			foreach (explode(' ', $pconfig['revokeserial']) as $serial) {
149
				$vserial = cert_validate_serial($serial, true, true);
150
				if ($vserial != null) {
151
					$revoke_list[] = $vserial;
152
				} else {
153
					$input_errors[] = gettext("Invalid serial in list (Must be ASN.1 integer compatible decimal or hex string).");
154
				}
155
			}
156
		}
157
		if (empty($pconfig['save']) && empty($pconfig['certref']) && empty($revoke_list)) {
158
			$input_errors[] = gettext("Select one or more certificates or enter a serial number to revoke.");
159
		}
160
		foreach ($pconfig['certref'] as $rcert) {
161
			$cert = lookup_cert($rcert);
162
			$cert = $cert['item'];
163
			if ($crl['caref'] == $cert['caref']) {
164
				$revoke_list[] = $cert;
165
			} else {
166
				$input_errors[] = gettext("CA mismatch between the Certificate and CRL. Unable to Revoke.");
167
			}
168
		}
169

    
170
		if (!$input_errors) {
171
			$crl['descr'] = $pconfig['descr'];
172
			$crl['lifetime'] = $pconfig['lifetime'];
173
			$crl['serial'] = $pconfig['serial'];
174
			if (!empty($revoke_list)) {
175
				$savemsg = "Revoked certificate(s) in CRL {$crl['descr']}.";
176
				$reason = (empty($pconfig['crlreason'])) ? 0 : $pconfig['crlreason'];
177
				foreach ($revoke_list as $cert) {
178
					cert_revoke($cert, $crl_item_config, $reason);
179
				}
180
				// refresh IPsec and OpenVPN CRLs
181
				openvpn_refresh_crls();
182
				ipsec_configure();
183
			} else {
184
				$savemsg = "Saved CRL {$crl['descr']}.";
185
			}
186
			write_config($savemsg);
187
			pfSenseHeader("system_crlmanager.php");
188
			exit;
189
		} else {
190
			$act = 'edit';
191
		}
192
		break;
193
	case 'delcert':
194
		if (!is_array($thiscrl['cert'])) {
195
			pfSenseHeader("system_crlmanager.php");
196
			exit;
197
		}
198
		$found = false;
199
		foreach ($thiscrl['cert'] as $acert) {
200
			if ($acert['refid'] == $_REQUEST['certref']) {
201
				$found = true;
202
				$thiscert = $acert;
203
			}
204
		}
205
		if (!$found) {
206
			pfSenseHeader("system_crlmanager.php");
207
			exit;
208
		}
209
		$certname = htmlspecialchars($thiscert['descr']);
210
		$crlname = htmlspecialchars($thiscrl['descr']);
211
		if (cert_unrevoke($thiscert, $crl_item_config)) {
212
			$savemsg = sprintf(gettext('Deleted Certificate %1$s from CRL %2$s.'), $certname, $crlname);
213
			$class = "success";
214
			// refresh IPsec and OpenVPN CRLs
215
			openvpn_refresh_crls();
216
			ipsec_configure();
217
			write_config($savemsg);
218
		} else {
219
			$savemsg = sprintf(gettext('Failed to delete Certificate %1$s from CRL %2$s.'), $certname, $crlname);
220
			$class = "danger";
221
		}
222
		$act="edit";
223
		break;
224
	case 'exp':
225
		/* Exporting the CRL contents*/
226
		crl_update($crl_item_config);
227
		send_user_download('data', base64_decode($thiscrl['text']), "{$thiscrl['descr']}.crl");
228
		break;
229
	default:
230
		break;
231
}
232

    
233
if ($_POST['save'] && empty($input_errors)) {
234
	$input_errors = array();
235
	$pconfig = $_POST;
236

    
237
	/* input validation */
238
	if (($pconfig['method'] == "existing") || ($act == "editimported")) {
239
		$reqdfields = explode(" ", "descr crltext");
240
		$reqdfieldsn = array(
241
			gettext("Descriptive name"),
242
			gettext("Certificate Revocation List data"));
243
	}
244
	if (($pconfig['method'] == "internal") ||
245
	    ($act == "addcert")) {
246
		$reqdfields = explode(" ", "descr caref");
247
		$reqdfieldsn = array(
248
			gettext("Descriptive name"),
249
			gettext("Certificate Authority"));
250
	}
251

    
252
	do_input_validation($_POST, $reqdfields, $reqdfieldsn, $input_errors);
253

    
254
	if (preg_match("/[\?\>\<\&\/\\\"\']/", $pconfig['descr'])) {
255
		array_push($input_errors, "The field 'Descriptive Name' contains invalid characters.");
256
	}
257
	if ($pconfig['lifetime'] > $max_lifetime) {
258
		$input_errors[] = gettext("Lifetime is longer than the maximum allowed value. Use a shorter lifetime.");
259
	}
260

    
261
	if ((strlen($pconfig['serial']) > 0) && !cert_validate_serial($pconfig['serial'])) {
262
		$input_errors[] = gettext("Please enter a valid integer serial number.");
263
	}
264

    
265
	/* save modifications */
266
	if (!$input_errors) {
267
		$result = false;
268

    
269
		if ($thiscrl) {
270
			$crl =& $thiscrl;
271
		} else {
272
			$crl = array();
273
			$crl['refid'] = uniqid();
274
		}
275

    
276
		$crl['descr'] = $pconfig['descr'];
277
		if ($act != "editimported") {
278
			$crl['caref'] = $pconfig['caref'];
279
			$crl['method'] = $pconfig['method'];
280
		}
281

    
282
		if (($pconfig['method'] == "existing") || ($act == "editimported")) {
283
			$crl['text'] = base64_encode($pconfig['crltext']);
284
		}
285

    
286
		if ($pconfig['method'] == "internal") {
287
			$crl['serial'] = empty($pconfig['serial']) ? '0' : $pconfig['serial'];
288
			$crl['lifetime'] = empty($pconfig['lifetime']) ? $default_lifetime : $pconfig['lifetime'];
289
			$crl['cert'] = array();
290
		}
291

    
292
		if (!$thiscrl) {
293
			config_set_path('crl/', $crl);
294
		} else {
295
			config_set_path("crl/{$crl_item_config['idx']}", $crl);
296
		}
297

    
298
		write_config("Saved CRL {$crl['descr']}");
299
		// refresh IPsec and OpenVPN CRLs
300
		openvpn_refresh_crls();
301
		ipsec_configure();
302
		pfSenseHeader("system_crlmanager.php");
303
	}
304
}
305

    
306
$pgtitle = array(gettext('System'), gettext('Certificates'), gettext('Revocation'));
307
$pglinks = array("", "system_camanager.php", "system_crlmanager.php");
308

    
309
if ($act == "new" || $act == gettext("Save") || $input_errors || $act == "edit") {
310
	$pgtitle[] = gettext('Edit');
311
	$pglinks[] = "@self";
312
}
313
include("head.inc");
314
?>
315

    
316
<script type="text/javascript">
317
//<![CDATA[
318

    
319
function method_change() {
320

    
321
	method = document.iform.method.value;
322

    
323
	switch (method) {
324
		case "internal":
325
			document.getElementById("existing").style.display="none";
326
			document.getElementById("internal").style.display="";
327
			break;
328
		case "existing":
329
			document.getElementById("existing").style.display="";
330
			document.getElementById("internal").style.display="none";
331
			break;
332
	}
333
}
334

    
335
//]]>
336
</script>
337

    
338
<?php
339

    
340
function build_method_list($importonly = false) {
341
	global $_POST, $crl_methods;
342

    
343
	$list = array();
344

    
345
	foreach ($crl_methods as $method => $desc) {
346
		if ($importonly && ($method != "existing")) {
347
			continue;
348
		}
349

    
350
		$list[$method] = $desc;
351
	}
352

    
353
	return($list);
354
}
355

    
356
function build_ca_list() {
357
	$list = array();
358

    
359
	foreach (config_get_path('ca', []) as $ca) {
360
		$list[$ca['refid']] = $ca['descr'];
361
	}
362

    
363
	return($list);
364
}
365

    
366
function build_cacert_list() {
367
	global $crl, $id;
368

    
369
	$list = array();
370
	foreach (config_get_path('cert', []) as $cert) {
371
		if ((isset($cert['caref']) && !empty($cert['caref'])) &&
372
		    ($cert['caref'] == $crl['caref']) &&
373
		    !is_cert_revoked($cert, $id)) {
374
			$list[$cert['refid']] = $cert['descr'];
375
		}
376
	}
377

    
378
	return($list);
379
}
380

    
381
if ($input_errors) {
382
	print_input_errors($input_errors);
383
}
384

    
385
if ($savemsg) {
386
	print_info_box($savemsg, $class);
387
}
388

    
389
$tab_array = array();
390
$tab_array[] = array(gettext('Authorities'), false, 'system_camanager.php');
391
$tab_array[] = array(gettext('Certificates'), false, 'system_certmanager.php');
392
$tab_array[] = array(gettext('Revocation'), true, 'system_crlmanager.php');
393
display_top_tabs($tab_array);
394

    
395
if ($act == "new" || $act == gettext("Save")) {
396
	$form = new Form();
397

    
398
	$section = new Form_Section('Create new Revocation List');
399

    
400
	$section->addInput(new Form_StaticText(
401
		'Certificate Authority',
402
		$crlca['descr']
403
	));
404

    
405
	if (!isset($id)) {
406
		$section->addInput(new Form_Select(
407
			'method',
408
			'*Method',
409
			$pconfig['method'],
410
			build_method_list((!isset($crlca['prv']) || empty($crlca['prv'])))
411
		));
412
	}
413

    
414
	$section->addInput(new Form_Input(
415
		'descr',
416
		'*Descriptive name',
417
		'text',
418
		$pconfig['descr']
419
	));
420

    
421
	$form->addGlobal(new Form_Input(
422
		'caref',
423
		null,
424
		'hidden',
425
		$pconfig['caref']
426
	));
427

    
428
	$form->add($section);
429

    
430
	$section = new Form_Section('Existing Certificate Revocation List');
431
	$section->addClass('existing');
432

    
433
	$section->addInput(new Form_Textarea(
434
		'crltext',
435
		'*CRL data',
436
		$pconfig['crltext']
437
		))->setHelp('Paste a Certificate Revocation List in X.509 CRL format here.');
438

    
439
	$form->add($section);
440

    
441
	$section = new Form_Section('Internal Certificate Revocation List');
442
	$section->addClass('internal');
443

    
444
	$section->addInput(new Form_Input(
445
		'lifetime',
446
		'Lifetime (Days)',
447
		'number',
448
		$pconfig['lifetime'],
449
		['max' => $max_lifetime]
450
	));
451

    
452
	$section->addInput(new Form_Input(
453
		'serial',
454
		'Serial',
455
		'number',
456
		$pconfig['serial'],
457
		['min' => '0']
458
	));
459

    
460
	$form->add($section);
461

    
462
	if (isset($id) && $thiscrl) {
463
		$form->addGlobal(new Form_Input(
464
			'id',
465
			null,
466
			'hidden',
467
			$id
468
		));
469
	}
470

    
471
	print($form);
472

    
473
} elseif ($act == "editimported") {
474

    
475
	$form = new Form();
476

    
477
	$section = new Form_Section('Edit Imported Certificate Revocation List');
478

    
479
	$section->addInput(new Form_Input(
480
		'descr',
481
		'*Descriptive name',
482
		'text',
483
		$thiscrl['descr']
484
	));
485

    
486
	$section->addInput(new Form_Textarea(
487
		'crltext',
488
		'*CRL data',
489
		!empty($thiscrl['text']) ? base64_decode($thiscrl['text']) : ''
490
	))->setHelp('Paste a Certificate Revocation List in X.509 CRL format here.');
491

    
492
	$form->addGlobal(new Form_Input(
493
		'id',
494
		null,
495
		'hidden',
496
		$id
497
	));
498

    
499
	$form->addGlobal(new Form_Input(
500
		'act',
501
		null,
502
		'hidden',
503
		'editimported'
504
	));
505

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

    
508
	print($form);
509

    
510
} elseif ($act == "edit") {
511
	$crl = $thiscrl;
512

    
513
	$form = new Form();
514

    
515
	$section = new Form_Section('Edit Internal Certificate Revocation List');
516

    
517
	$section->addInput(new Form_Input(
518
		'descr',
519
		'*Descriptive name',
520
		'text',
521
		$crl['descr']
522
	));
523

    
524
	$section->addInput(new Form_Input(
525
		'lifetime',
526
		'CRL Lifetime (Days)',
527
		'number',
528
		$crl['lifetime'],
529
		['max' => $max_lifetime]
530
	));
531

    
532
	$section->addInput(new Form_Input(
533
		'serial',
534
		'CRL Serial',
535
		'number',
536
		$crl['serial'],
537
		['min' => '0']
538
	));
539

    
540
	$form->add($section);
541
?>
542

    
543
	<div class="panel panel-default">
544
		<div class="panel-heading"><h2 class="panel-title"><?=gettext("Revoked Certificates in CRL") . ': ' . $crl['descr']?></h2></div>
545
		<div class="panel-body table-responsive">
546
<?php
547
	if (!is_array($crl['cert']) || (count($crl['cert']) == 0)) {
548
		print_info_box(gettext("No certificates found for this CRL."), 'danger');
549
	} else {
550
?>
551
			<table class="table table-striped table-hover table-condensed sortable-theme-bootstrap" data-sortable>
552
				<thead>
553
					<tr>
554
						<th><?=gettext("Serial")?></th>
555
						<th><?=gettext("Certificate Name")?></th>
556
						<th><?=gettext("Revocation Reason")?></th>
557
						<th><?=gettext("Revoked At")?></th>
558
						<th></th>
559
					</tr>
560
				</thead>
561
				<tbody>
562
<?php
563
		foreach ($crl['cert'] as $cert):
564
			$name = empty($cert['descr']) ? gettext('Revoked by Serial') : htmlspecialchars($cert['descr']);
565
			$serial = crl_get_entry_serial($cert);
566
			if (strlen($serial) == 0) {
567
				$serial = gettext("Invalid");
568
			} ?>
569
					<tr>
570
						<td><?=htmlspecialchars($serial);?></td>
571
						<td><?=$name; ?></td>
572
						<td><?=$openssl_crl_status[$cert['reason']]; ?></td>
573
						<td><?=date("D M j G:i:s T Y", $cert['revoke_time']); ?></td>
574
						<td class="list">
575
							<a href="system_crlmanager.php?act=delcert&amp;id=<?=$crl['refid']; ?>&amp;certref=<?=$cert['refid']; ?>" usepost>
576
								<i class="fa-solid fa-trash-can" title="<?=gettext("Delete this certificate from the CRL")?>" alt="<?=gettext("Delete this certificate from the CRL")?>"></i>
577
							</a>
578
						</td>
579
					</tr>
580
<?php
581
		endforeach;
582
?>
583
				</tbody>
584
			</table>
585
<?php
586
	}
587
?>
588
		</div>
589
	</div>
590
<?php
591

    
592
	$section = new Form_Section('Revoke Certificates');
593

    
594
	$section->addInput(new Form_Select(
595
		'crlreason',
596
		'Reason',
597
		-1,
598
		$openssl_crl_status
599
		))->setHelp('Select the reason for which the certificates are being revoked.');
600

    
601
	$cacert_list = build_cacert_list();
602
	if (count($cacert_list) == 0) {
603
		print_info_box(gettext("No certificates found for this CA."), 'danger');
604
	} else {
605
		$section->addInput(new Form_Select(
606
			'certref',
607
			'Revoke Certificates',
608
			$pconfig['certref'],
609
			$cacert_list,
610
			true
611
			))->addClass('multiselect')
612
			->setHelp('Hold down CTRL (PC)/COMMAND (Mac) key to select multiple items.');
613
	}
614

    
615
	$section->addInput(new Form_Input(
616
		'revokeserial',
617
		'Revoke by Serial',
618
		'text',
619
		$pconfig['revokeserial']
620
	))->setHelp('List of certificate serial numbers to revoke (separated by spaces)');
621

    
622
	$form->addGlobal(new Form_Button(
623
		'submit',
624
		'Add',
625
		null,
626
		'fa-solid fa-plus'
627
		))->addClass('btn-success btn-sm');
628

    
629
	$form->addGlobal(new Form_Input(
630
		'id',
631
		null,
632
		'hidden',
633
		$crl['refid']
634
	));
635

    
636
	$form->addGlobal(new Form_Input(
637
		'act',
638
		null,
639
		'hidden',
640
		'addcert'
641
	));
642

    
643
	$form->addGlobal(new Form_Input(
644
		'crlref',
645
		null,
646
		'hidden',
647
		$crl['refid']
648
	));
649

    
650
	$form->add($section);
651

    
652
	print($form);
653
} else {
654
?>
655

    
656
	<div class="panel panel-default">
657
		<div class="panel-heading"><h2 class="panel-title"><?=gettext("Certificate Revocation Lists")?></h2></div>
658
		<div class="panel-body table-responsive">
659
			<table class="table table-striped table-hover table-condensed table-rowdblclickedit">
660
				<thead>
661
					<tr>
662
						<th><?=gettext("CA")?></th>
663
						<th><?=gettext("Name")?></th>
664
						<th><?=gettext("Internal")?></th>
665
						<th><?=gettext("Certificates")?></th>
666
						<th><?=gettext("In Use")?></th>
667
						<th><?=gettext("Actions")?></th>
668
					</tr>
669
				</thead>
670
				<tbody>
671
<?php
672
	$pluginparams = array();
673
	$pluginparams['type'] = 'certificates';
674
	$pluginparams['event'] = 'used_crl';
675
	$certificates_used_by_packages = pkg_call_plugins('plugin_certificates', $pluginparams);
676
	// Map CRLs to CAs in one pass
677
	$ca_crl_map = array();
678
	foreach (config_get_path('crl', []) as $crl) {
679
		$ca_crl_map[$crl['caref']][] = $crl['refid'];
680
	}
681

    
682
	$i = 0;
683
	foreach (config_get_path('ca', []) as $ca):
684
		$caname = htmlspecialchars($ca['descr']);
685
		if (is_array($ca_crl_map[$ca['refid']])):
686
			foreach ($ca_crl_map[$ca['refid']] as $crl):
687
				$tmpcrl = lookup_crl($crl);
688
				$tmpcrl = $tmpcrl['item'];
689
				$internal = is_crl_internal($tmpcrl);
690
				if ($internal && (!isset($tmpcrl['cert']) || empty($tmpcrl['cert'])) ) {
691
					$tmpcrl['cert'] = array();
692
				}
693
				$inuse = crl_in_use($tmpcrl['refid']);
694
?>
695
					<tr>
696
						<td><?=$caname?></td>
697
						<td><?=$tmpcrl['descr']; ?></td>
698
						<td><i class="<?=($internal) ? "fa-solid fa-check" : "fa-solid fa-times"; ?>"></i></td>
699
						<td><?=($internal) ? count($tmpcrl['cert']) : "Unknown (imported)"; ?></td>
700
						<td>
701
						<?php if (is_openvpn_server_crl($tmpcrl['refid'])): ?>
702
							<?=gettext("OpenVPN Server")?>
703
						<?php endif?>
704
						<?php echo cert_usedby_description($tmpcrl['refid'], $certificates_used_by_packages); ?>
705
						</td>
706
						<td>
707
							<a href="system_crlmanager.php?act=exp&amp;id=<?=$tmpcrl['refid']?>" class="fa-solid fa-download" title="<?=gettext("Export CRL")?>" ></a>
708
<?php
709
				if ($internal): ?>
710
							<a href="system_crlmanager.php?act=edit&amp;id=<?=$tmpcrl['refid']?>" class="fa-solid fa-pencil" title="<?=gettext("Edit CRL")?>"></a>
711
<?php
712
				else:
713
?>
714
							<a href="system_crlmanager.php?act=editimported&amp;id=<?=$tmpcrl['refid']?>" class="fa-solid fa-pencil" title="<?=gettext("Edit CRL")?>"></a>
715
<?php			endif;
716
				if (!$inuse):
717
?>
718
							<a href="system_crlmanager.php?act=del&amp;id=<?=$tmpcrl['refid']?>" class="fa-solid fa-trash-can" title="<?=gettext("Delete CRL")?>" usepost></a>
719
<?php
720
				endif;
721
?>
722
						</td>
723
					</tr>
724
<?php
725
				$i++;
726
				endforeach;
727
			endif;
728
			$i++;
729
		endforeach;
730
?>
731
				</tbody>
732
			</table>
733
		</div>
734
	</div>
735

    
736
<?php
737
	$form = new Form(false);
738
	$section = new Form_Section('Create or Import a New Certificate Revocation List');
739
	$group = new Form_Group(null);
740
	$group->add(new Form_Select(
741
		'caref',
742
		'Certificate Authority',
743
		null,
744
		build_ca_list()
745
		))->setHelp('Select a Certificate Authority for the new CRL');
746
	$group->add(new Form_Button(
747
		'submit',
748
		'Add',
749
		null,
750
		'fa-solid fa-plus'
751
		))->addClass('btn-success btn-sm');
752
	$section->add($group);
753
	$form->addGlobal(new Form_Input(
754
		'act',
755
		null,
756
		'hidden',
757
		'new'
758
	));
759
	$form->add($section);
760
	print($form);
761
}
762

    
763
?>
764

    
765
<script type="text/javascript">
766
//<![CDATA[
767
events.push(function() {
768

    
769
	// Hides all elements of the specified class. This will usually be a section or group
770
	function hideClass(s_class, hide) {
771
		if (hide) {
772
			$('.' + s_class).hide();
773
		} else {
774
			$('.' + s_class).show();
775
		}
776
	}
777

    
778
	// When the 'method" selector is changed, we show/hide certain sections
779
	$('#method').on('change', function() {
780
		hideClass('internal', ($('#method').val() == 'existing'));
781
		hideClass('existing', ($('#method').val() == 'internal'));
782
	});
783

    
784
	hideClass('internal', ($('#method').val() == 'existing'));
785
	hideClass('existing', ($('#method').val() == 'internal'));
786
	$('.multiselect').attr("size","<?= max(3, min(15, count($cacert_list))) ?>");
787
});
788
//]]>
789
</script>
790

    
791
<?php include("foot.inc");
(197-197/230)