$_POST['domain']], 'zone') !== []) output(403, _('This zone already exists on the service.')); exescape([ CONF['dns']['kdig_path'], ltrim(strstr($_POST['domain'], '.'), '.'), 'NS', '+short', ...(CONF['ns']['local_only_check'] ? ['@' . CONF['reg']['address']] : []), ], $parentAuthoritatives, $code); if ($code !== 0) output(500, 'Unable to query parent name servers.'); if ($parentAuthoritatives === []) output(403, _('Parent zone\'s name servers not found.')); foreach ($parentAuthoritatives as $parentAuthoritative) checkAbsoluteDomainFormat($parentAuthoritative); exescape([ CONF['dns']['kdig_path'], $_POST['domain'], 'NS', '@' . (CONF['ns']['local_only_check'] ? CONF['reg']['address'] : $parentAuthoritatives[0]), '+noidn' ], $results); if (preg_match('/^' . preg_quote($_POST['domain'], '/') . '[\t ]+[0-9]{1,8}[\t ]+IN[\t ]+NS[\t ]+(?[0-9a-f]{8})-(?[0-9a-f]{32})\._domain-verification\.' . preg_quote(SERVER_NAME, '/') . '\.$/Dm', implode(LF, $results), $matches) !== 1) output(403, _('NS authentication record not found.')); checkAuthToken($matches['salt'], $matches['hash']); rateLimit(); insert('zones', [ 'zone' => $_POST['domain'], 'username' => $_SESSION['id'], ]); $knotZonePath = CONF['ns']['knot_zones_path'] . '/' . $_POST['domain'] . 'zone'; $knotZone = implode(' ', [ $_POST['domain'], SOA_VALUES['ttl'], 'SOA', CONF['ns']['servers'][0], SOA_VALUES['email'], 1, SOA_VALUES['refresh'], SOA_VALUES['retry'], SOA_VALUES['expire'], SOA_VALUES['negative'], ]) . LF; foreach (CONF['ns']['servers'] as $server) $knotZone .= $_POST['domain'] . ' 86400 NS ' . $server . LF; $knotZone .= $_POST['domain'] . ' 86400 CSYNC 0 1 NS' . LF; if (is_int(file_put_contents($knotZonePath, $knotZone)) !== true) output(500, 'Failed to write new zone file.'); if (chmod($knotZonePath, 0660) !== true) output(500, 'Failed to chmod new zone file.'); knotcConfExec([ ['conf-set', 'zone[' . $_POST['domain'] . ']'], ['conf-set', 'zone[' . $_POST['domain'] . '].template', 'servnest'], ]); output(200, _('Zone created.'));