mirror of
https://github.com/getnamingo/registry.git
synced 2025-05-10 16:58:34 +02:00
Added host:create EPP command
This commit is contained in:
parent
1d31db8e6c
commit
2bcba151f4
4 changed files with 217 additions and 1 deletions
|
@ -842,7 +842,7 @@ class EppWriter {
|
||||||
$writer->writeAttribute('xmlns:host', 'urn:ietf:params:xml:ns:host-1.0');
|
$writer->writeAttribute('xmlns:host', 'urn:ietf:params:xml:ns:host-1.0');
|
||||||
$writer->writeAttribute('xsi:schemaLocation', 'urn:ietf:params:xml:ns:host-1.0 host-1.0.xsd');
|
$writer->writeAttribute('xsi:schemaLocation', 'urn:ietf:params:xml:ns:host-1.0 host-1.0.xsd');
|
||||||
$writer->writeElement('host:name', $resp['name']);
|
$writer->writeElement('host:name', $resp['name']);
|
||||||
$writer->writeElement('host:crDate', $resp['crDate']);
|
$writer->writeElement('host:crDate', gmdate('Y-m-d\TH:i:s\.0\Z', strtotime($resp['crDate'])));
|
||||||
$writer->endElement(); // End of 'host:creData'
|
$writer->endElement(); // End of 'host:creData'
|
||||||
$writer->endElement(); // End of 'resData'
|
$writer->endElement(); // End of 'resData'
|
||||||
}
|
}
|
||||||
|
|
|
@ -388,4 +388,172 @@ function processContactCreate($conn, $db, $xml, $clid, $database_type) {
|
||||||
$epp = new EPP\EppWriter();
|
$epp = new EPP\EppWriter();
|
||||||
$xml = $epp->epp_writer($response);
|
$xml = $epp->epp_writer($response);
|
||||||
sendEppResponse($conn, $xml);
|
sendEppResponse($conn, $xml);
|
||||||
|
}
|
||||||
|
|
||||||
|
function processHostCreate($conn, $db, $xml, $clid, $database_type) {
|
||||||
|
$hostName = $xml->command->create->children('urn:ietf:params:xml:ns:host-1.0')->create->name;
|
||||||
|
$clTRID = (string) $xml->command->clTRID;
|
||||||
|
|
||||||
|
$hostName = strtoupper($hostName);
|
||||||
|
if (preg_match('/^([A-Z0-9]([A-Z0-9-]{0,61}[A-Z0-9]){0,1}\.){1,125}[A-Z0-9]([A-Z0-9-]{0,61}[A-Z0-9])$/i', $hostName) && strlen($hostName) < 254) {
|
||||||
|
$host_id_already_exist = $db->query("SELECT id FROM host WHERE name = '$hostName' LIMIT 1")->fetchColumn();
|
||||||
|
if ($host_id_already_exist) {
|
||||||
|
sendEppError($conn, 2302, 'host:name already exists');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sendEppError($conn, 2005, 'Invalid host:name');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$host_addr_list = $xml->xpath('//addr');
|
||||||
|
if (count($host_addr_list) > 13) {
|
||||||
|
sendEppError($conn, 2306, 'Parameter value policy error');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$stmt = $db->prepare("SELECT id FROM registrar WHERE clid = :clid LIMIT 1");
|
||||||
|
$stmt->bindParam(':clid', $clid, PDO::PARAM_STR);
|
||||||
|
$stmt->execute();
|
||||||
|
$clid = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||||
|
$clid = $clid['id'];
|
||||||
|
|
||||||
|
$nsArr = [];
|
||||||
|
|
||||||
|
foreach ($host_addr_list as $node) {
|
||||||
|
$addr = (string)$node;
|
||||||
|
$addr_type = (string) $node['ip'] ?? 'v4';
|
||||||
|
|
||||||
|
if ($addr_type === 'v6') {
|
||||||
|
$addr = normalize_v6_address($addr);
|
||||||
|
} else {
|
||||||
|
$addr = normalize_v4_address($addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// v6 IP validation
|
||||||
|
if ($addr_type === 'v6' && !filter_var($addr, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
|
||||||
|
sendEppError($conn, 2005, 'Invalid host:addr v6');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// v4 IP validation
|
||||||
|
if ($addr_type !== 'v6' && !filter_var($addr, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
|
||||||
|
sendEppError($conn, 2005, 'Invalid host:addr v4');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for duplicate IPs
|
||||||
|
if (isset($nsArr[$addr_type][$addr])) {
|
||||||
|
sendEppError($conn, 2306, 'Duplicated host:addr');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$nsArr[$addr_type][$addr] = $addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
$internal_host = false;
|
||||||
|
|
||||||
|
$query = "SELECT tld FROM domain_tld";
|
||||||
|
foreach ($db->query($query) as $row) {
|
||||||
|
if (preg_match("/" . preg_quote(strtoupper($row['tld']), '/') . "$/i", $hostName)) {
|
||||||
|
$internal_host = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($internal_host) {
|
||||||
|
$domain_exist = false;
|
||||||
|
$clid_domain = 0;
|
||||||
|
$superordinate_dom = 0;
|
||||||
|
|
||||||
|
$stmt = $db->prepare("SELECT id,clid,name FROM domain");
|
||||||
|
$stmt->execute();
|
||||||
|
|
||||||
|
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||||
|
if (strpos($hostName, $row['name']) !== false) {
|
||||||
|
$domain_exist = true;
|
||||||
|
$clid_domain = $row['clid'];
|
||||||
|
$superordinate_dom = $row['id'];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$domain_exist) {
|
||||||
|
sendEppError($conn, 2303, 'Object does not exist');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($clid != $clid_domain) {
|
||||||
|
sendEppError($conn, 2201, 'Authorization error');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$stmt = $db->prepare("INSERT INTO host (name,domain_id,clid,crid,crdate) VALUES(?,?,?,?,CURRENT_TIMESTAMP)");
|
||||||
|
$stmt->execute([$hostName, $superordinate_dom, $clid, $clid]);
|
||||||
|
$host_id = $db->lastInsertId();
|
||||||
|
|
||||||
|
$host_addr_list = $xml->xpath('host:addr');
|
||||||
|
|
||||||
|
foreach ($host_addr_list as $node) {
|
||||||
|
$addr = (string) $node;
|
||||||
|
$addr_type = isset($node['ip']) ? (string) $node['ip'] : 'v4';
|
||||||
|
|
||||||
|
if ($addr_type == 'v6') {
|
||||||
|
$addr = normalize_v6_address($addr);
|
||||||
|
} else {
|
||||||
|
$addr = normalize_v4_address($addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
$addr_type = ($addr_type == 'v6') ? 6 : 4;
|
||||||
|
|
||||||
|
$stmt = $db->prepare("INSERT INTO host_addr (host_id,addr,ip) VALUES(?,?,?)");
|
||||||
|
$stmt->execute([$host_id, $addr, $addr_type]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$stmt = $db->prepare("SELECT crdate FROM host WHERE name = ? LIMIT 1");
|
||||||
|
$stmt->execute([$hostName]);
|
||||||
|
$crdate = $stmt->fetchColumn();
|
||||||
|
|
||||||
|
$response = [
|
||||||
|
'command' => 'create_host',
|
||||||
|
'resultCode' => 1000,
|
||||||
|
'lang' => 'en-US',
|
||||||
|
'message' => 'Command completed successfully',
|
||||||
|
'name' => $hostName,
|
||||||
|
'crDate' => $crdate,
|
||||||
|
'clTRID' => $clTRID,
|
||||||
|
'svTRID' => generateSvTRID(),
|
||||||
|
];
|
||||||
|
|
||||||
|
$epp = new EPP\EppWriter();
|
||||||
|
$xml = $epp->epp_writer($response);
|
||||||
|
sendEppResponse($conn, $xml);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
$stmt = $db->prepare("INSERT INTO host (name,clid,crid,crdate) VALUES(?,?,?,CURRENT_TIMESTAMP)");
|
||||||
|
$stmt->execute([$hostName, $clid, $clid]);
|
||||||
|
|
||||||
|
$host_id = $db->lastInsertId();
|
||||||
|
|
||||||
|
$stmt = $db->prepare("SELECT crdate FROM host WHERE name = ? LIMIT 1");
|
||||||
|
$stmt->execute([$hostName]);
|
||||||
|
$crdate = $stmt->fetchColumn();
|
||||||
|
|
||||||
|
$response = [
|
||||||
|
'command' => 'create_host',
|
||||||
|
'resultCode' => 1000,
|
||||||
|
'lang' => 'en-US',
|
||||||
|
'message' => 'Command completed successfully',
|
||||||
|
'name' => $hostName,
|
||||||
|
'crDate' => $crdate,
|
||||||
|
'clTRID' => $clTRID,
|
||||||
|
'svTRID' => generateSvTRID(),
|
||||||
|
];
|
||||||
|
|
||||||
|
$epp = new EPP\EppWriter();
|
||||||
|
$xml = $epp->epp_writer($response);
|
||||||
|
sendEppResponse($conn, $xml);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
11
epp/epp.php
11
epp/epp.php
|
@ -212,6 +212,17 @@ $server->handle(function (Connection $conn) use ($table, $db, $c) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case isset($xml->command->create) && isset($xml->command->create->children('urn:ietf:params:xml:ns:host-1.0')->create):
|
||||||
|
{
|
||||||
|
$data = $table->get($connId);
|
||||||
|
if (!$data || $data['logged_in'] !== 1) {
|
||||||
|
sendEppError($conn, 2202, 'Authorization error');
|
||||||
|
$conn->close();
|
||||||
|
}
|
||||||
|
processHostCreate($conn, $db, $xml, $data['clid'], $c['db_type']);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case isset($xml->command->info) && isset($xml->command->info->children('urn:ietf:params:xml:ns:host-1.0')->info):
|
case isset($xml->command->info) && isset($xml->command->info->children('urn:ietf:params:xml:ns:host-1.0')->info):
|
||||||
{
|
{
|
||||||
$data = $table->get($connId);
|
$data = $table->get($connId);
|
||||||
|
|
|
@ -164,4 +164,41 @@ function validate_label($label, $pdo) {
|
||||||
$server->send($fd, "Domain name invalid format");
|
$server->send($fd, "Domain name invalid format");
|
||||||
return 'Invalid domain name format, please review registry policy about accepted labels';
|
return 'Invalid domain name format, please review registry policy about accepted labels';
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalize_v4_address($v4) {
|
||||||
|
// Remove leading zeros from the first octet
|
||||||
|
$v4 = preg_replace('/^0+(\d)/', '$1', $v4);
|
||||||
|
|
||||||
|
// Remove leading zeros from successive octets
|
||||||
|
$v4 = preg_replace('/\.0+(\d)/', '.$1', $v4);
|
||||||
|
|
||||||
|
return $v4;
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalize_v6_address($v6) {
|
||||||
|
// Upper case any alphabetics
|
||||||
|
$v6 = strtoupper($v6);
|
||||||
|
|
||||||
|
// Remove leading zeros from the first word
|
||||||
|
$v6 = preg_replace('/^0+([\dA-F])/', '$1', $v6);
|
||||||
|
|
||||||
|
// Remove leading zeros from successive words
|
||||||
|
$v6 = preg_replace('/:0+([\dA-F])/', ':$1', $v6);
|
||||||
|
|
||||||
|
// Introduce a :: if there isn't one already
|
||||||
|
if (strpos($v6, '::') === false) {
|
||||||
|
$v6 = preg_replace('/:0:0:/', '::', $v6);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove initial zero word before a ::
|
||||||
|
$v6 = preg_replace('/^0+::/', '::', $v6);
|
||||||
|
|
||||||
|
// Remove other zero words before a ::
|
||||||
|
$v6 = preg_replace('/(:0)+::/', '::', $v6);
|
||||||
|
|
||||||
|
// Remove zero words following a ::
|
||||||
|
$v6 = preg_replace('/:(:0)+/', ':', $v6);
|
||||||
|
|
||||||
|
return $v6;
|
||||||
}
|
}
|
Loading…
Add table
Reference in a new issue