2023-07-17 19:15:18 +00:00
|
|
|
<?php declare(strict_types=1);
|
2022-12-20 20:17:03 +00:00
|
|
|
|
2023-08-13 23:54:54 +00:00
|
|
|
$domain = formatAbsoluteDomain($_POST['domain']);
|
2022-12-20 20:17:03 +00:00
|
|
|
|
2023-10-07 22:50:48 +00:00
|
|
|
if (query('select', 'zones', ['zone' => $domain], ['zone']) !== [])
|
2023-01-21 00:27:52 +00:00
|
|
|
output(403, _('This zone already exists on the service.'));
|
2022-12-20 20:17:03 +00:00
|
|
|
|
2023-08-13 23:54:54 +00:00
|
|
|
$parent_domain = ltrim(strstr($domain, '.'), '.');
|
|
|
|
$parent_authoritatives = array_column(kdig(name: $parent_domain, type: 'NS', server: (CONF['ns']['local_only_check'] ? CONF['reg']['address'] : NULL))['answerRRs'] ?? [], 'rdataNS');
|
2023-08-13 16:52:34 +00:00
|
|
|
if ($parent_authoritatives === [])
|
2023-01-21 00:27:52 +00:00
|
|
|
output(403, _('Parent zone\'s name servers not found.'));
|
2023-08-13 16:52:34 +00:00
|
|
|
foreach ($parent_authoritatives as $parent_authoritative)
|
|
|
|
checkAbsoluteDomainFormat($parent_authoritative);
|
2022-12-20 20:17:03 +00:00
|
|
|
|
2023-08-14 15:24:16 +00:00
|
|
|
foreach ($parent_authoritatives as $i => $parent_authoritative) {
|
|
|
|
if ($i === 3)
|
|
|
|
output(403, sprintf(_('The %s first tried name servers failed to answer.'), $i));
|
|
|
|
try {
|
|
|
|
$results = kdig(name: $domain, type: 'NS', server: (CONF['ns']['local_only_check'] ? CONF['reg']['address'] : $parent_authoritative));
|
|
|
|
} catch (KdigException) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
$ns_records = array_column($results['authorityRRs'] ?? [], 'rdataNS');
|
2023-08-13 16:52:34 +00:00
|
|
|
if (preg_match('/^(?<salt>[0-9a-f]{8})-(?<hash>[0-9a-f]{32})\._domain-verification\.' . preg_quote(SERVER_NAME, '/') . '\.$/Dm', implode(LF, $ns_records), $matches) !== 1)
|
2023-01-21 00:27:52 +00:00
|
|
|
output(403, _('NS authentication record not found.'));
|
2022-12-20 20:17:03 +00:00
|
|
|
|
|
|
|
checkAuthToken($matches['salt'], $matches['hash']);
|
|
|
|
|
|
|
|
rateLimit();
|
|
|
|
|
|
|
|
insert('zones', [
|
2023-08-13 23:54:54 +00:00
|
|
|
'zone' => $domain,
|
2022-12-20 20:17:03 +00:00
|
|
|
'username' => $_SESSION['id'],
|
|
|
|
]);
|
|
|
|
|
2023-08-13 23:54:54 +00:00
|
|
|
$zone_path = CONF['ns']['knot_zones_path'] . '/' . $domain . 'zone';
|
|
|
|
$zone_content = implode(' ', [
|
|
|
|
$domain,
|
2023-07-30 23:13:06 +00:00
|
|
|
NS_SOA_VALUES['ttl'],
|
2022-12-20 20:17:03 +00:00
|
|
|
'SOA',
|
|
|
|
CONF['ns']['servers'][0],
|
2023-07-30 23:13:06 +00:00
|
|
|
NS_SOA_VALUES['email'],
|
2022-12-20 20:17:03 +00:00
|
|
|
1,
|
2023-07-30 23:13:06 +00:00
|
|
|
NS_SOA_VALUES['refresh'],
|
|
|
|
NS_SOA_VALUES['retry'],
|
|
|
|
NS_SOA_VALUES['expire'],
|
|
|
|
NS_SOA_VALUES['negative'],
|
2022-12-20 20:17:03 +00:00
|
|
|
]) . LF;
|
|
|
|
foreach (CONF['ns']['servers'] as $server)
|
2023-08-13 23:54:54 +00:00
|
|
|
$zone_content .= $domain . ' 86400 NS ' . $server . LF;
|
|
|
|
$zone_content .= $domain . ' 86400 CSYNC 0 1 NS' . LF;
|
|
|
|
if (file_put_contents($zone_path, $zone_content) === false)
|
2022-12-20 20:17:03 +00:00
|
|
|
output(500, 'Failed to write new zone file.');
|
2023-08-13 23:54:54 +00:00
|
|
|
if (chmod($zone_path, 0660) !== true)
|
2022-12-20 20:17:03 +00:00
|
|
|
output(500, 'Failed to chmod new zone file.');
|
|
|
|
|
|
|
|
knotcConfExec([
|
2023-08-13 23:54:54 +00:00
|
|
|
['conf-set', 'zone[' . $domain . ']'],
|
|
|
|
['conf-set', 'zone[' . $domain . '].template', 'servnest'],
|
2022-12-20 20:17:03 +00:00
|
|
|
]);
|
|
|
|
|
2023-01-21 00:27:52 +00:00
|
|
|
output(200, _('Zone created.'));
|