Project

General

Profile

Feature #16960 » 16960-b.patch

Jim Pingle, 07/23/2026 06:34 PM

View differences:

src/etc/inc/priv/user.priv.inc
166 166
$priv_list['page-openvpn-client-advanced']['descr'] = gettext("Allow edit access to the 'OpenVPN: Servers' Advanced settings field.");
167 167
$priv_list['page-openvpn-client-advanced']['warn'] = "standard-warning-root";
168 168

  
169
$priv_list['page-services-dhcpserver-custom'] = array();
170
$priv_list['page-services-dhcpserver-custom']['name'] = gettext("WebCfg - Services: DHCP Server: Edit Custom Configuration");
171
$priv_list['page-services-dhcpserver-custom']['descr'] = gettext("Allow edit access to the 'Services: DHCP Server' Custom Configuration fields.");
172
$priv_list['page-services-dhcpserver-custom']['warn'] = "standard-warning-root";
173

  
174
$priv_list['page-services-dhcpv6server-custom'] = array();
175
$priv_list['page-services-dhcpv6server-custom']['name'] = gettext("WebCfg - Services: DHCPv6 Server: Edit Custom Configuration");
176
$priv_list['page-services-dhcpv6server-custom']['descr'] = gettext("Allow edit access to the 'Services: DHCPv6 Server' Custom Configuration fields.");
177
$priv_list['page-services-dhcpv6server-custom']['warn'] = "standard-warning-root";
178

  
169 179
?>
src/usr/local/pfSense/include/www/services_dhcp.inc
24 24
require_once('interfaces.inc');
25 25
require_once('pfsense-utils.inc');
26 26

  
27
/* custom config can run commands as root, so it has its own privilege */
28
function dhcp_can_edit_custom_config(bool $v6 = false): bool {
29
	$user_entry = getUserEntry($_SESSION['Username']);
30
	$user_entry = $user_entry['item'];
31
	$priv = $v6 ? 'page-services-dhcpv6server-custom'
32
		    : 'page-services-dhcpserver-custom';
33

  
34
	return (isAdminUID($_SESSION['Username']) ||
35
	    userHasPrivilege($user_entry, $priv) ||
36
	    userHasPrivilege($user_entry, 'page-all'));
37
}
38

  
27 39
function kea_defaults(string $key): int|string {
28 40
	/* throws an exception if $key isn't matched */
29 41
	return (match($key) {
......
442 454
		}
443 455
	}
444 456

  
445
	if (!empty($_POST['custom_kea_config'])) {
446
		array_set_path($pconfig, 'custom_kea_config', base64_encode($_POST['custom_kea_config']));
457
	$custom_priv_error = false;
458
	if (dhcp_can_edit_custom_config()) {
459
		if (!empty($_POST['custom_kea_config'])) {
460
			array_set_path($pconfig, 'custom_kea_config', base64_encode($_POST['custom_kea_config']));
461
		} else {
462
			array_del_path($pconfig, 'custom_kea_config');
463
		}
447 464
	} else {
448
		array_del_path($pconfig, 'custom_kea_config');
465
		$old_custom = base64_decode(array_get_path($old_config, 'custom_kea_config', ''));
466
		if (isset($_POST['custom_kea_config']) && ($_POST['custom_kea_config'] !== $old_custom)) {
467
			$custom_priv_error = true;
468
		}
469
		/* preserve stored value */
470
		if (!empty($old_custom)) {
471
			array_set_path($pconfig, 'custom_kea_config', base64_encode($old_custom));
472
		} else {
473
			array_del_path($pconfig, 'custom_kea_config');
474
		}
449 475
	}
450 476

  
451 477
	/* don't leave empty ha config section */
......
454 480
	}
455 481

  
456 482
	$input_errors = dhcp_validate_settings_post($pconfig);
483
	if ($custom_priv_error) {
484
		$input_errors[] = gettext('This user does not have sufficient privileges to edit the Custom Configuration field.');
485
	}
457 486
	if (!$input_errors && ($pconfig !== $old_config)) {
458 487
		config_set_path('kea', $pconfig);
459 488
		write_config(gettext('DHCP Server - Settings changed'));
......
550 579
		}
551 580
	}
552 581

  
553
	if (!empty($_POST['custom_kea_config'])) {
554
		array_set_path($pconfig, 'custom_kea_config', base64_encode($_POST['custom_kea_config']));
582
	$custom_priv_error = false;
583
	if (dhcp_can_edit_custom_config(true)) {
584
		if (!empty($_POST['custom_kea_config'])) {
585
			array_set_path($pconfig, 'custom_kea_config', base64_encode($_POST['custom_kea_config']));
586
		} else {
587
			array_del_path($pconfig, 'custom_kea_config');
588
		}
555 589
	} else {
556
		array_del_path($pconfig, 'custom_kea_config');
590
		$old_custom = base64_decode(array_get_path($old_config, 'custom_kea_config', ''));
591
		if (isset($_POST['custom_kea_config']) && ($_POST['custom_kea_config'] !== $old_custom)) {
592
			$custom_priv_error = true;
593
		}
594
		/* preserve stored value */
595
		if (!empty($old_custom)) {
596
			array_set_path($pconfig, 'custom_kea_config', base64_encode($old_custom));
597
		} else {
598
			array_del_path($pconfig, 'custom_kea_config');
599
		}
557 600
	}
558 601

  
559 602
	/* don't leave empty ha config section */
......
562 605
	}
563 606

  
564 607
	$input_errors = dhcp_validate_settings_post($pconfig);
608
	if ($custom_priv_error) {
609
		$input_errors[] = gettext('This user does not have sufficient privileges to edit the Custom Configuration field.');
610
	}
565 611
	if (!$input_errors && ($pconfig !== $old_config)) {
566 612
		config_set_path('kea6', $pconfig);
567 613
		write_config(gettext('DHCPv6 Server - Settings changed'));
src/usr/local/www/services_dhcp.php
625 625

  
626 626
	/* validate custom config */
627 627
	if (dhcp_is_backend('kea')) {
628
		if (!empty($_POST['custom_kea_config'])) {
629
			$json = json_decode($_POST['custom_kea_config'], true);
630
			if (!is_array($json) || (json_last_error() !== JSON_ERROR_NONE)) {
631
				$input_errors[] = gettext('Custom configuration is not a well formed JSON object.');
628
		if (dhcp_can_edit_custom_config()) {
629
			if (!empty($_POST['custom_kea_config'])) {
630
				$json = json_decode($_POST['custom_kea_config'], true);
631
				if (!is_array($json) || (json_last_error() !== JSON_ERROR_NONE)) {
632
					$input_errors[] = gettext('Custom configuration is not a well formed JSON object.');
633
				}
634
			}
635
		} else {
636
			$stored_custom = base64_decode(array_get_path($dhcpdconf, 'custom_kea_config', ''));
637
			if (isset($_POST['custom_kea_config']) && ($_POST['custom_kea_config'] !== $stored_custom)) {
638
				$input_errors[] = gettext('This user does not have sufficient privileges to edit the Custom Configuration field.');
632 639
			}
640
			/* show the stored value, not the submitted one */
641
			$pconfig['custom_kea_config'] = $stored_custom;
633 642
		}
634 643
	}
635 644

  
......
817 826
			$dhcpdconf['omapi_key_algorithm'] = $_POST['omapi_key_algorithm'];
818 827
		}
819 828

  
820
		if (dhcp_is_backend('kea')) {
829
		if (dhcp_is_backend('kea') && dhcp_can_edit_custom_config()) {
821 830
			$dhcpdconf['custom_kea_config'] = base64_encode($_POST['custom_kea_config']);
822 831
		}
823 832

  
......
1862 1871

  
1863 1872
if (dhcp_is_backend('kea')):
1864 1873
$section = new Form_Section(gettext('Custom Configuration'));
1865
$section->addInput(new Form_Textarea(
1874
$custom_config = new Form_Textarea(
1866 1875
	'custom_kea_config',
1867 1876
	gettext('JSON Configuration'),
1868 1877
	array_get_path($pconfig, 'custom_kea_config')
1869
))->setWidth(8)->setHelp(gettext('JSON to be merged into the "%1$s" section of the generated Kea DHCPv4 configuration.%2$sThe input must be a well formed JSON object and should not include the "%1$s" key itself.'), $kea_section, '<br/>');
1878
);
1879
if (!dhcp_can_edit_custom_config()) {
1880
	$custom_config->setDisabled();
1881
}
1882
$section->addInput($custom_config)->setWidth(8)->setHelp(gettext('JSON to be merged into the "%1$s" section of the generated Kea DHCPv4 configuration.%2$sThe input must be a well formed JSON object and should not include the "%1$s" key itself.'), $kea_section, '<br/>');
1870 1883
$form->add($section);
1871 1884
endif;
1872 1885

  
src/usr/local/www/services_dhcp_edit.php
423 423

  
424 424
	/* validate custom config */
425 425
	if (dhcp_is_backend('kea')) {
426
		if (!empty($_POST['custom_kea_config'])) {
427
			$json = json_decode($_POST['custom_kea_config'], true);
428
			if (!is_array($json) || (json_last_error() !== JSON_ERROR_NONE)) {
429
				$input_errors[] = gettext('Custom configuration is not a well formed JSON object.');
426
		if (dhcp_can_edit_custom_config()) {
427
			if (!empty($_POST['custom_kea_config'])) {
428
				$json = json_decode($_POST['custom_kea_config'], true);
429
				if (!is_array($json) || (json_last_error() !== JSON_ERROR_NONE)) {
430
					$input_errors[] = gettext('Custom configuration is not a well formed JSON object.');
431
				}
430 432
			}
433
		} else {
434
			$stored_custom = is_array($this_map_config) ? base64_decode(array_get_path($this_map_config, 'custom_kea_config', '')) : '';
435
			if (isset($_POST['custom_kea_config']) && ($_POST['custom_kea_config'] !== $stored_custom)) {
436
				$input_errors[] = gettext('This user does not have sufficient privileges to edit the Custom Configuration field.');
437
			}
438
			/* show the stored value, not the submitted one */
439
			$pconfig['custom_kea_config'] = $stored_custom;
431 440
		}
432 441
	}
433 442

  
......
503 512
		$mapent['numberoptions'] = $pconfig['numberoptions'];
504 513

  
505 514
		if (dhcp_is_backend('kea')) {
506
			$mapent['custom_kea_config'] = base64_encode($_POST['custom_kea_config']);
515
			if (dhcp_can_edit_custom_config()) {
516
				$mapent['custom_kea_config'] = base64_encode($_POST['custom_kea_config']);
517
			} elseif (!empty($this_map_config['custom_kea_config'])) {
518
				/* preserve stored value */
519
				$mapent['custom_kea_config'] = $this_map_config['custom_kea_config'];
520
			}
507 521
		}
508 522

  
509 523
		if ($this_map_config) {
......
1112 1126

  
1113 1127
if (dhcp_is_backend('kea')):
1114 1128
$section = new Form_Section(gettext('Custom Configuration'));
1115
$section->addInput(new Form_Textarea(
1129
$custom_config = new Form_Textarea(
1116 1130
	'custom_kea_config',
1117 1131
	gettext('JSON Configuration'),
1118 1132
	array_get_path($pconfig, 'custom_kea_config')
1119
))->setWidth(8)->setHelp(gettext('JSON to be merged into the "%1$s" section of the generated Kea DHCPv4 configuration.%2$sThe input must be a well formed JSON object and should not include the "%1$s" key itself.'), 'reservation', '<br/>');
1133
);
1134
if (!dhcp_can_edit_custom_config()) {
1135
	$custom_config->setDisabled();
1136
}
1137
$section->addInput($custom_config)->setWidth(8)->setHelp(gettext('JSON to be merged into the "%1$s" section of the generated Kea DHCPv4 configuration.%2$sThe input must be a well formed JSON object and should not include the "%1$s" key itself.'), 'reservation', '<br/>');
1120 1138
$form->add($section);
1121 1139
endif;
1122 1140

  
src/usr/local/www/services_dhcp_settings.php
359 359
$form->add($section);
360 360

  
361 361
$section = new Form_Section(gettext('Custom Configuration'));
362
$section->addInput(new Form_Textarea(
362
$custom_config = new Form_Textarea(
363 363
	'custom_kea_config',
364 364
	gettext('JSON Configuration'),
365 365
	array_get_path($pconfig, 'custom_kea_config')
366
))->setWidth(8)->setHelp(gettext('JSON to be merged into the "%1$s" section of the generated Kea DHCPv4 configuration.%2$sThe input must be a well formed JSON object and should not include the "%1$s" key itself.'), 'Dhcp4', '<br/>');
366
);
367
if (!dhcp_can_edit_custom_config()) {
368
	$custom_config->setDisabled();
369
}
370
$section->addInput($custom_config)->setWidth(8)->setHelp(gettext('JSON to be merged into the "%1$s" section of the generated Kea DHCPv4 configuration.%2$sThe input must be a well formed JSON object and should not include the "%1$s" key itself.'), 'Dhcp4', '<br/>');
367 371
$form->add($section);
368 372

  
369 373
$form->addGlobal(new Form_Input(
src/usr/local/www/services_dhcpv6.php
453 453

  
454 454
	/* validate custom config */
455 455
	if (dhcp_is_backend('kea')) {
456
		if (!empty($_POST['custom_kea_config'])) {
457
			$json = json_decode($_POST['custom_kea_config'], true);
458
			if (!is_array($json) || (json_last_error() !== JSON_ERROR_NONE)) {
459
				$input_errors[] = gettext('Custom configuration is not a well formed JSON object.');
456
		if (dhcp_can_edit_custom_config(true)) {
457
			if (!empty($_POST['custom_kea_config'])) {
458
				$json = json_decode($_POST['custom_kea_config'], true);
459
				if (!is_array($json) || (json_last_error() !== JSON_ERROR_NONE)) {
460
					$input_errors[] = gettext('Custom configuration is not a well formed JSON object.');
461
				}
462
			}
463
		} else {
464
			$stored_custom = base64_decode(array_get_path($dhcpdconf, 'custom_kea_config', ''));
465
			if (isset($_POST['custom_kea_config']) && ($_POST['custom_kea_config'] !== $stored_custom)) {
466
				$input_errors[] = gettext('This user does not have sufficient privileges to edit the Custom Configuration field.');
460 467
			}
468
			/* show the stored value, not the submitted one */
469
			$pconfig['custom_kea_config'] = $stored_custom;
461 470
		}
462 471
	}
463 472

  
......
580 589

  
581 590
		$dhcpdconf['numberoptions'] = $numberoptions;
582 591

  
583
		if (dhcp_is_backend('kea')) {
592
		if (dhcp_is_backend('kea') && dhcp_can_edit_custom_config(true)) {
584 593
			$dhcpdconf['custom_kea_config'] = base64_encode($_POST['custom_kea_config']);
585 594
		}
586 595

  
......
1434 1443

  
1435 1444
if (dhcp_is_backend('kea')):
1436 1445
$section = new Form_Section(gettext('Custom Configuration'));
1437
$section->addInput(new Form_Textarea(
1446
$custom_config = new Form_Textarea(
1438 1447
	'custom_kea_config',
1439 1448
	gettext('JSON Configuration'),
1440 1449
	array_get_path($pconfig, 'custom_kea_config')
1441
))->setWidth(8)->setHelp(gettext('JSON to be merged into the "%1$s" section of the generated Kea DHCPv6 configuration.%2$sThe input must be a well formed JSON object and should not include the "%1$s" key itself.'), $kea_section, '<br/>');
1450
);
1451
if (!dhcp_can_edit_custom_config(true)) {
1452
	$custom_config->setDisabled();
1453
}
1454
$section->addInput($custom_config)->setWidth(8)->setHelp(gettext('JSON to be merged into the "%1$s" section of the generated Kea DHCPv6 configuration.%2$sThe input must be a well formed JSON object and should not include the "%1$s" key itself.'), $kea_section, '<br/>');
1442 1455
$form->add($section);
1443 1456
endif;
1444 1457

  
src/usr/local/www/services_dhcpv6_edit.php
176 176

  
177 177
	/* validate custom config */
178 178
	if (dhcp_is_backend('kea')) {
179
		if (!empty($_POST['custom_kea_config'])) {
180
			$json = json_decode($_POST['custom_kea_config'], true);
181
			if (!is_array($json) || (json_last_error() !== JSON_ERROR_NONE)) {
182
				$input_errors[] = gettext('Custom configuration is not a well formed JSON object.');
179
		if (dhcp_can_edit_custom_config(true)) {
180
			if (!empty($_POST['custom_kea_config'])) {
181
				$json = json_decode($_POST['custom_kea_config'], true);
182
				if (!is_array($json) || (json_last_error() !== JSON_ERROR_NONE)) {
183
					$input_errors[] = gettext('Custom configuration is not a well formed JSON object.');
184
				}
183 185
			}
186
		} else {
187
			$stored_custom = is_array($this_map_config) ? base64_decode(array_get_path($this_map_config, 'custom_kea_config', '')) : '';
188
			if (isset($_POST['custom_kea_config']) && ($_POST['custom_kea_config'] !== $stored_custom)) {
189
				$input_errors[] = gettext('This user does not have sufficient privileges to edit the Custom Configuration field.');
190
			}
191
			/* show the stored value, not the submitted one */
192
			$pconfig['custom_kea_config'] = $stored_custom;
184 193
		}
185 194
	}
186 195

  
......
198 207
			if (!empty($_POST['pdprefix'])) {
199 208
				$mapent['pdprefix'] = text_to_compressed_ip6($_POST['pdprefix']);
200 209
			}
201
			$mapent['custom_kea_config'] = base64_encode($_POST['custom_kea_config']);
210
			if (dhcp_can_edit_custom_config(true)) {
211
				$mapent['custom_kea_config'] = base64_encode($_POST['custom_kea_config']);
212
			} elseif (!empty($this_map_config['custom_kea_config'])) {
213
				/* preserve stored value */
214
				$mapent['custom_kea_config'] = $this_map_config['custom_kea_config'];
215
			}
202 216
		}
203 217

  
204 218
		if ($this_map_config) {
......
354 368

  
355 369
if (dhcp_is_backend('kea')):
356 370
$section = new Form_Section(gettext('Custom Configuration'));
357
$section->addInput(new Form_Textarea(
371
$custom_config = new Form_Textarea(
358 372
	'custom_kea_config',
359 373
	gettext('JSON Configuration'),
360 374
	array_get_path($pconfig, 'custom_kea_config')
361
))->setWidth(8)->setHelp(gettext('JSON to be merged into the "%1$s" section of the generated Kea DHCPv6 configuration.%2$sThe input must be a well formed JSON object and should not include the "%1$s" key itself.'), 'reservation', '<br/>');
375
);
376
if (!dhcp_can_edit_custom_config(true)) {
377
	$custom_config->setDisabled();
378
}
379
$section->addInput($custom_config)->setWidth(8)->setHelp(gettext('JSON to be merged into the "%1$s" section of the generated Kea DHCPv6 configuration.%2$sThe input must be a well formed JSON object and should not include the "%1$s" key itself.'), 'reservation', '<br/>');
362 380
$form->add($section);
363 381
endif;
364 382

  
src/usr/local/www/services_dhcpv6_settings.php
373 373
$form->add($section);
374 374

  
375 375
$section = new Form_Section(gettext('Custom Configuration'));
376
$section->addInput(new Form_Textarea(
376
$custom_config = new Form_Textarea(
377 377
	'custom_kea_config',
378 378
	gettext('JSON Configuration'),
379 379
	array_get_path($pconfig, 'custom_kea_config')
380
))->setWidth(8)->setHelp(gettext('JSON to be merged into the "%1$s" section of the generated Kea DHCPv6 configuration.%2$sThe input must be a well formed JSON object and should not include the "%1$s" key itself.'), 'Dhcp6', '<br/>');
380
);
381
if (!dhcp_can_edit_custom_config(true)) {
382
	$custom_config->setDisabled();
383
}
384
$section->addInput($custom_config)->setWidth(8)->setHelp(gettext('JSON to be merged into the "%1$s" section of the generated Kea DHCPv6 configuration.%2$sThe input must be a well formed JSON object and should not include the "%1$s" key itself.'), 'Dhcp6', '<br/>');
381 385
$form->add($section);
382 386

  
383 387
$form->addGlobal(new Form_Input(
(2-2/2)