$domain], ['zone']) !== []) output(403, _('This zone already exists on the service.')); $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'); if ($parent_authoritatives === []) output(403, _('Parent zone\'s name servers not found.')); foreach ($parent_authoritatives as $parent_authoritative) checkAbsoluteDomainFormat($parent_authoritative); 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'); if (preg_match('/^(?[0-9a-f]{8})-(?[0-9a-f]{32})\._domain-verification\.' . preg_quote(SERVER_NAME, '/') . '\.$/Dm', implode(LF, $ns_records), $matches) !== 1) output(403, _('NS authentication record not found.')); checkAuthToken($matches['salt'], $matches['hash']); rateLimit(); insert('zones', [ 'zone' => $domain, 'username' => $_SESSION['id'], ]); $zone_path = CONF['ns']['knot_zones_path'] . '/' . $domain . 'zone'; $zone_content = implode(' ', [ $domain, NS_SOA_VALUES['ttl'], 'SOA', CONF['ns']['servers'][0], NS_SOA_VALUES['email'], 1, NS_SOA_VALUES['refresh'], NS_SOA_VALUES['retry'], NS_SOA_VALUES['expire'], NS_SOA_VALUES['negative'], ]) . LF; foreach (CONF['ns']['servers'] as $server) $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) output(500, 'Failed to write new zone file.'); if (chmod($zone_path, 0660) !== true) output(500, 'Failed to chmod new zone file.'); knotcConfExec([ ['conf-set', 'zone[' . $domain . ']'], ['conf-set', 'zone[' . $domain . '].template', 'servnest'], ]); output(200, _('Zone created.'));