servnest/fn/reg.php

116 lines
3.3 KiB
PHP

<?php declare(strict_types=1);
const SUBDOMAIN_REGEX = '^(?!\-)(?!..\-\-)[a-z0-9-]{4,63}(?<!\-)$';
const REG_TEXTAREA_MAX_CHARACTERS = 5000;
const REG_ALLOWED_TYPES = ['NS', 'DS', 'AAAA', 'A'];
function regListUserDomains(): array {
if (isset($_SESSION['id']))
return query('select', 'registry', ['username' => $_SESSION['id']], ['domain']);
return [];
}
function regCheckDomainPossession(string $domain): void {
if (in_array($domain, regListUserDomains(), true) !== true)
output(403, 'You don\'t own this domain on the registry.');
}
function regStripDomain(string $domain, string $content): string {
return preg_replace('/^(?:[a-z0-9._-]+\.)?' . preg_quote($domain, '/') . '[\t ]+.+$/Dm', '', $content);
}
function regDeleteDomain(string $domain, string $user_id): void {
// Delete domain from registry file
$path = CONF['reg']['suffixes_path'] . '/' . regParseDomain($domain)['suffix'] . 'zone';
if (($content = file_get_contents($path)) === false)
output(500, 'Failed to read current registry file.');
if (file_put_contents($path, regStripDomain($domain, $content)) === false)
output(500, 'Failed to write new registry file.');
try {
DB->beginTransaction();
$conditions = [
'domain' => $domain,
'username' => $user_id,
];
insert('registry-history', [
'domain' => $domain,
'creation' => query('select', 'registry', $conditions, ['creation'])[0],
'expiration' => date('Y-m'),
]);
query('delete', 'registry', $conditions);
DB->commit();
} catch (Exception $e) {
DB->rollback();
output(500, 'Database error.', [$e->getMessage()]);
}
}
function regParseDomain(string $domain): array {
$parts = explode('.', $domain, 2);
$subdomain = $parts[0];
$suffix = $parts[1];
if (array_key_exists($suffix, CONF['reg']['suffixes']) !== true)
output(403, 'This suffix doesn\'t exist.');
return [
'subdomain' => $subdomain,
'suffix' => $suffix,
];
}
function regParseRecord(string $domain, array $record): array {
checkAbsoluteDomainFormat($record['domain']);
if ($record['domain'] !== $_POST['domain']) {
if ($record['type'] !== 'ip')
output(403, _('You can only set a NS/DS record for an apex domain.'));
else if (!str_ends_with($record['domain'], '.' . $domain))
output(403, _('You can\'t set a record for another domain.'));
}
$new_rec = [
$record['domain'],
CONF['reg']['ttl'],
$record['type'],
];
if ($record['type'] === 'DS') {
if (!in_array($record['algo'], ['8', '13', '14', '15', '16'], true))
output(403, 'Wrong value for <code>algo</code>.');
if ((preg_match('/^[0-9]{1,6}$/D', $record['keytag'])) !== 1 OR !($record['keytag'] >= 1) OR !($record['keytag'] <= 65535))
output(403, 'Wrong value for <code>keytag</code>.');
if ($record['dt'] !== '2' AND $record['dt'] !== '4')
output(403, 'Wrong value for <code>dt</code>.');
if (preg_match('/^(?:[0-9a-fA-F]{64}|[0-9a-fA-F]{96})$/D', $record['key']) !== 1)
output(403, 'Wrong value for <code>key</code>.');
return [
...$new_rec,
$record['keytag'],
$record['algo'],
$record['dt'],
$record['key'],
];
}
if ($record['type'] === 'NS')
return [
...$new_rec,
formatAbsoluteDomain($record['ns']),
];
if ($record['type'] === 'ip')
return [
$record['domain'],
CONF['reg']['ttl'],
checkIpFormat($record['ip']),
$record['ip'],
];
}