2021-02-17 22:48:49 +01:00
|
|
|
<?php
|
|
|
|
|
2023-06-20 00:36:58 +02:00
|
|
|
function parseZoneFile(string $zone_content, array $types, bool|string $filter_domain = false): array {
|
2022-12-20 21:17:03 +01:00
|
|
|
$parsed_zone_content = [];
|
2023-01-23 01:14:59 +01:00
|
|
|
foreach (explode(LF, $zone_content) as $zone_line) {
|
2022-12-20 21:17:03 +01:00
|
|
|
if ($zone_line === '' OR str_starts_with($zone_line, ';'))
|
|
|
|
continue; // Ignore empty lines and comments
|
|
|
|
$elements = preg_split('/[\t ]+/', $zone_line, 4);
|
|
|
|
if ($filter_domain !== false AND !str_ends_with($elements[0], $filter_domain))
|
|
|
|
continue; // Ignore records for other domains
|
2023-04-21 19:01:46 +02:00
|
|
|
if (!in_array($elements[2], $types, true))
|
|
|
|
continue; // Ignore records generated by Knot
|
2022-12-20 21:17:03 +01:00
|
|
|
array_push($parsed_zone_content, array_map('htmlspecialchars', $elements));
|
|
|
|
}
|
|
|
|
return $parsed_zone_content;
|
|
|
|
}
|
|
|
|
|
2023-06-19 02:15:43 +02:00
|
|
|
function knotc(array $cmds, array &$output = NULL, int &$return_code = NULL): void {
|
|
|
|
exescape([
|
|
|
|
CONF['dns']['knotc_path'],
|
|
|
|
'--blocking',
|
|
|
|
'--timeout',
|
|
|
|
'3',
|
|
|
|
'--',
|
|
|
|
...$cmds,
|
|
|
|
], $output, $return_code);
|
|
|
|
}
|
|
|
|
|
|
|
|
function knotcConfExec(array $cmds): void {
|
|
|
|
knotc(['conf-begin'], $output['begin'], $code['begin']);
|
2022-06-18 04:22:05 +02:00
|
|
|
if ($code['begin'] !== 0)
|
2022-09-15 19:17:48 +02:00
|
|
|
output(500, 'knotcConfExec: <code>knotc</code> failed with exit code <samp>' . $code['begin'] . '</samp>: <samp>' . $output['begin'][0] . '</samp>.');
|
2022-06-18 04:22:05 +02:00
|
|
|
|
|
|
|
foreach ($cmds as $cmd) {
|
2023-06-19 02:15:43 +02:00
|
|
|
knotc($cmd, $output['op'], $code['op']);
|
2022-06-18 04:22:05 +02:00
|
|
|
if ($code['op'] !== 0) {
|
2023-06-19 02:15:43 +02:00
|
|
|
knotc(['conf-abort']);
|
2022-09-15 19:17:48 +02:00
|
|
|
output(500, 'knotcConfExec: <code>knotc</code> failed with exit code <samp>' . $code['op'] . '</samp>: <samp>' . $output['op'][0] . '</samp>.');
|
2022-06-18 04:22:05 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-19 02:15:43 +02:00
|
|
|
knotc(['conf-commit'], $output['commit'], $code['commit']);
|
2022-06-18 04:22:05 +02:00
|
|
|
if ($code['commit'] !== 0) {
|
2023-06-19 02:15:43 +02:00
|
|
|
knotc(['conf-abort']);
|
2022-09-15 19:17:48 +02:00
|
|
|
output(500, 'knotcConfExec: <code>knotc</code> failed with exit code <samp>' . $code['commit'] . '</samp>: <samp>' . $output['commit'][0] . '</samp>.');
|
2022-06-18 04:22:05 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-20 00:36:58 +02:00
|
|
|
function knotcZoneExec(string $zone, array $cmd, string $action = NULL): void {
|
2022-12-13 16:52:10 +01:00
|
|
|
$action = checkAction($action ?? $_POST['action']);
|
2022-05-25 01:16:41 +02:00
|
|
|
|
2023-06-19 02:15:43 +02:00
|
|
|
knotc(['zone-begin', $zone], $output['begin'], $code['begin']);
|
2022-05-25 01:16:41 +02:00
|
|
|
if ($code['begin'] !== 0)
|
2022-09-15 19:17:48 +02:00
|
|
|
output(500, 'knotcZoneExec: <code>knotc</code> failed with exit code <samp>' . $code['begin'] . '</samp>: <samp>' . $output['begin'][0] . '</samp>.');
|
2022-05-25 01:16:41 +02:00
|
|
|
|
2023-06-19 02:15:43 +02:00
|
|
|
knotc(['zone-' . $action . 'set', $zone, ...$cmd], $output['op'], $code['op']);
|
2022-06-10 00:38:05 +02:00
|
|
|
if ($code['op'] !== 0) {
|
2023-06-19 02:15:43 +02:00
|
|
|
knotc(['zone-abort', $zone]);
|
2022-09-15 19:17:48 +02:00
|
|
|
output(500, 'knotcZoneExec: <code>knotc</code> failed with exit code <samp>' . $code['op'] . '</samp>: <samp>' . $output['op'][0] . '</samp>.');
|
2022-06-10 00:38:05 +02:00
|
|
|
}
|
2022-05-25 01:16:41 +02:00
|
|
|
|
2023-06-19 02:15:43 +02:00
|
|
|
knotc(['zone-commit', $zone], $output['commit'], $code['commit']);
|
2022-06-10 00:38:05 +02:00
|
|
|
if ($code['commit'] !== 0) {
|
2023-06-19 02:15:43 +02:00
|
|
|
knotc(['zone-abort', $zone]);
|
2022-09-15 19:17:48 +02:00
|
|
|
output(500, 'knotcZoneExec: <code>knotc</code> failed with exit code <samp>' . $code['commit'] . '</samp>: <samp>' . $output['commit'][0] . '</samp>.');
|
2022-06-10 00:38:05 +02:00
|
|
|
}
|
2022-05-25 01:16:41 +02:00
|
|
|
}
|
|
|
|
|
2023-06-20 00:36:58 +02:00
|
|
|
function checkIpFormat(string $ip): string {
|
2022-05-20 02:19:45 +02:00
|
|
|
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4))
|
2022-11-20 15:11:54 +01:00
|
|
|
return 'A';
|
2022-05-20 02:19:45 +02:00
|
|
|
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6))
|
2022-11-20 15:11:54 +01:00
|
|
|
return 'AAAA';
|
2023-01-21 01:27:52 +01:00
|
|
|
output(403, _('IP address malformed.'));
|
2021-02-17 22:48:49 +01:00
|
|
|
}
|
|
|
|
|
2023-06-20 00:36:58 +02:00
|
|
|
function checkAbsoluteDomainFormat(string $domain): void { // If the domain must end with a dot
|
2023-04-21 19:01:46 +02:00
|
|
|
if (!filter_var($domain, FILTER_VALIDATE_DOMAIN) OR preg_match('/^(?=^.{1,254}$)([a-z0-9_-]{1,63}\.){2,127}$/D', $domain) !== 1)
|
2023-01-21 01:27:52 +01:00
|
|
|
output(403, _('Domain malformed.'));
|
2021-02-17 22:48:49 +01:00
|
|
|
}
|
|
|
|
|
2023-06-20 00:36:58 +02:00
|
|
|
function formatEndWithDot(string $str): string {
|
2022-06-15 15:30:18 +02:00
|
|
|
if (!str_ends_with($str, '.'))
|
|
|
|
$str .= '.';
|
|
|
|
return $str;
|
|
|
|
}
|
|
|
|
|
2023-06-20 00:36:58 +02:00
|
|
|
function formatAbsoluteDomain(string $domain): string {
|
2022-06-15 15:30:18 +02:00
|
|
|
$domain = formatEndWithDot(strtolower($domain));
|
|
|
|
checkAbsoluteDomainFormat($domain);
|
|
|
|
return $domain;
|
|
|
|
}
|
|
|
|
|
2023-06-20 00:36:58 +02:00
|
|
|
function checkAction(string $action): string {
|
2022-06-12 01:31:16 +02:00
|
|
|
return match ($action) {
|
|
|
|
'add' => '',
|
|
|
|
'delete' => 'un',
|
2022-09-15 19:17:48 +02:00
|
|
|
default => output(403, 'Wrong value for action.'),
|
2022-06-12 01:31:16 +02:00
|
|
|
};
|
2021-02-17 22:48:49 +01:00
|
|
|
}
|