2023-07-17 19:15:18 +00:00
|
|
|
<?php declare(strict_types=1);
|
2021-02-17 21:48:49 +00:00
|
|
|
|
2023-06-04 22:18:10 +00:00
|
|
|
const SUBDOMAIN_REGEX = '^(?!\-)(?!..\-\-)[a-z0-9-]{4,63}(?<!\-)$';
|
2022-11-20 17:17:03 +00:00
|
|
|
|
2023-07-30 23:13:06 +00:00
|
|
|
const REG_TEXTAREA_MAX_CHARACTERS = 5000;
|
|
|
|
const REG_ALLOWED_TYPES = ['NS', 'DS', 'AAAA', 'A'];
|
|
|
|
|
2023-06-19 22:36:58 +00:00
|
|
|
function regListUserDomains(): array {
|
2022-12-20 20:17:03 +00:00
|
|
|
if (isset($_SESSION['id']))
|
2023-10-07 22:50:48 +00:00
|
|
|
return query('select', 'registry', ['username' => $_SESSION['id']], ['domain']);
|
2022-12-20 20:17:03 +00:00
|
|
|
return [];
|
2021-02-18 21:40:16 +00:00
|
|
|
}
|
|
|
|
|
2023-06-19 22:36:58 +00:00
|
|
|
function regCheckDomainPossession(string $domain): void {
|
2022-12-20 20:17:03 +00:00
|
|
|
if (in_array($domain, regListUserDomains(), true) !== true)
|
2023-01-21 00:27:52 +00:00
|
|
|
output(403, 'You don\'t own this domain on the registry.');
|
2021-02-18 21:40:16 +00:00
|
|
|
}
|
|
|
|
|
2023-07-30 23:13:06 +00:00
|
|
|
function regStripDomain(string $domain, string $content): string {
|
|
|
|
return preg_replace('/^(?:[a-z0-9._-]+\.)?' . preg_quote($domain, '/') . '[\t ]+.+$/Dm', '', $content);
|
|
|
|
}
|
|
|
|
|
2023-06-19 22:36:58 +00:00
|
|
|
function regDeleteDomain(string $domain, string $user_id): void {
|
2022-06-18 02:22:05 +00:00
|
|
|
// Delete domain from registry file
|
2023-01-23 00:14:59 +00:00
|
|
|
$path = CONF['reg']['suffixes_path'] . '/' . regParseDomain($domain)['suffix'] . 'zone';
|
2023-07-30 23:13:06 +00:00
|
|
|
if (($content = file_get_contents($path)) === false)
|
2023-01-23 00:14:59 +00:00
|
|
|
output(500, 'Failed to read current registry file.');
|
2023-07-30 23:13:06 +00:00
|
|
|
if (file_put_contents($path, regStripDomain($domain, $content)) === false)
|
2022-09-15 17:17:48 +00:00
|
|
|
output(500, 'Failed to write new registry file.');
|
2022-06-18 02:22:05 +00:00
|
|
|
|
2023-03-25 15:26:05 +00:00
|
|
|
try {
|
|
|
|
DB->beginTransaction();
|
|
|
|
|
|
|
|
$conditions = [
|
|
|
|
'domain' => $domain,
|
2023-06-08 15:36:44 +00:00
|
|
|
'username' => $user_id,
|
2023-03-25 15:26:05 +00:00
|
|
|
];
|
|
|
|
|
|
|
|
insert('registry-history', [
|
|
|
|
'domain' => $domain,
|
2023-10-07 22:50:48 +00:00
|
|
|
'creation' => query('select', 'registry', $conditions, ['creation'])[0],
|
2023-03-25 15:26:05 +00:00
|
|
|
'expiration' => date('Y-m'),
|
|
|
|
]);
|
|
|
|
|
|
|
|
query('delete', 'registry', $conditions);
|
|
|
|
|
|
|
|
DB->commit();
|
|
|
|
} catch (Exception $e) {
|
|
|
|
DB->rollback();
|
|
|
|
output(500, 'Database error.', [$e->getMessage()]);
|
|
|
|
}
|
2022-06-18 02:22:05 +00:00
|
|
|
}
|
2023-01-23 00:14:59 +00:00
|
|
|
|
2023-06-19 22:36:58 +00:00
|
|
|
function regParseDomain(string $domain): array {
|
2023-01-23 00:14:59 +00:00
|
|
|
$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,
|
|
|
|
];
|
|
|
|
}
|
2023-07-30 23:13:06 +00:00
|
|
|
|
|
|
|
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'],
|
|
|
|
];
|
|
|
|
}
|