Project

General

Profile

Download (20 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

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

    
58
$act = $_REQUEST['act'];
59

    
60
$cacert_list = array();
61

    
62
if (!empty($id)) {
63
	$crl_item_config = lookup_crl($id);
64
	$thiscrl = &$crl_item_config['item'];
65
}
66

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

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

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

    
118
		do_input_validation($_POST, $reqdfields, $reqdfieldsn, $input_errors);
119

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

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

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

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

    
230
if ($_POST['save'] && empty($input_errors)) {
231
	$input_errors = array();
232
	$pconfig = $_POST;
233

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

    
249
	do_input_validation($_POST, $reqdfields, $reqdfieldsn, $input_errors);
250

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

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

    
262
	/* save modifications */
263
	if (!$input_errors) {
264
		$result = false;
265

    
266
		if ($thiscrl) {
267
			$crl =& $thiscrl;
268
		} else {
269
			$crl = array();
270
			$crl['refid'] = uniqid();
271
		}
272

    
273
		$crl['descr'] = $pconfig['descr'];
274
		if ($act != "editimported") {
275
			$crl['caref'] = $pconfig['caref'];
276
			$crl['method'] = $pconfig['method'];
277
		}
278

    
279
		if (($pconfig['method'] == "existing") || ($act == "editimported")) {
280
			$crl['text'] = base64_encode($pconfig['crltext']);
281
		}
282

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

    
289
		if (!$thiscrl) {
290
			config_set_path('crl/', $crl);
291
		} else {
292
			config_set_path("crl/{$crl_item_config['idx']}", $crl);
293
		}
294

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

    
303
$pgtitle = array(gettext('System'), gettext('Certificates'), gettext('Revocation'));
304
$pglinks = array("", "system_camanager.php", "system_crlmanager.php");
305

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

    
313
<script type="text/javascript">
314
//<![CDATA[
315

    
316
function method_change() {
317

    
318
	method = document.iform.method.value;
319

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

    
332
//]]>
333
</script>
334

    
335
<?php
336

    
337
function build_method_list($importonly = false) {
338
	global $_POST, $crl_methods;
339

    
340
	$list = array();
341

    
342
	foreach ($crl_methods as $method => $desc) {
343
		if ($importonly && ($method != "existing")) {
344
			continue;
345
		}
346

    
347
		$list[$method] = $desc;
348
	}
349

    
350
	return($list);
351
}
352

    
353
function build_ca_list() {
354
	$list = array();
355

    
356
	foreach (config_get_path('ca', []) as $ca) {
357
		$list[$ca['refid']] = $ca['descr'];
358
	}
359

    
360
	return($list);
361
}
362

    
363
function build_cacert_list() {
364
	global $crl, $id;
365

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

    
375
	return($list);
376
}
377

    
378
if ($input_errors) {
379
	print_input_errors($input_errors);
380
}
381

    
382
if ($savemsg) {
383
	print_info_box($savemsg, $class);
384
}
385

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

    
392
if ($act == "new" || $act == gettext("Save")) {
393
	$form = new Form();
394

    
395
	$section = new Form_Section('Create new Revocation List');
396

    
397
	$section->addInput(new Form_StaticText(
398
		'Certificate Authority',
399
		$crlca['descr']
400
	));
401

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

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

    
418
	$form->addGlobal(new Form_Input(
419
		'caref',
420
		null,
421
		'hidden',
422
		$pconfig['caref']
423
	));
424

    
425
	$form->add($section);
426

    
427
	$section = new Form_Section('Existing Certificate Revocation List');
428
	$section->addClass('existing');
429

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

    
436
	$form->add($section);
437

    
438
	$section = new Form_Section('Internal Certificate Revocation List');
439
	$section->addClass('internal');
440

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

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

    
457
	$form->add($section);
458

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

    
468
	print($form);
469

    
470
} elseif ($act == "editimported") {
471

    
472
	$form = new Form();
473

    
474
	$section = new Form_Section('Edit Imported Certificate Revocation List');
475

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

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

    
489
	$form->addGlobal(new Form_Input(
490
		'id',
491
		null,
492
		'hidden',
493
		$id
494
	));
495

    
496
	$form->addGlobal(new Form_Input(
497
		'act',
498
		null,
499
		'hidden',
500
		'editimported'
501
	));
502

    
503
	$form->add($section);
504

    
505
	print($form);
506

    
507
} elseif ($act == "edit") {
508
	$crl = $thiscrl;
509

    
510
	$form = new Form();
511

    
512
	$section = new Form_Section('Edit Internal Certificate Revocation List');
513

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

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

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

    
537
	$form->add($section);
538
?>
539

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

    
589
	$section = new Form_Section('Revoke Certificates');
590

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

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

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

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

    
626
	$form->addGlobal(new Form_Input(
627
		'id',
628
		null,
629
		'hidden',
630
		$crl['refid']
631
	));
632

    
633
	$form->addGlobal(new Form_Input(
634
		'act',
635
		null,
636
		'hidden',
637
		'addcert'
638
	));
639

    
640
	$form->addGlobal(new Form_Input(
641
		'crlref',
642
		null,
643
		'hidden',
644
		$crl['refid']
645
	));
646

    
647
	$form->add($section);
648

    
649
	print($form);
650
} else {
651
?>
652

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

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

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

    
760
?>
761

    
762
<script type="text/javascript">
763
//<![CDATA[
764
events.push(function() {
765

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

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

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

    
788
<?php include("foot.inc");
(199-199/232)