mirror of
https://github.com/getnamingo/registry.git
synced 2025-05-22 12:29:22 +02:00
More RST updates
This commit is contained in:
parent
b11a80e0fb
commit
73db314105
4 changed files with 232 additions and 34 deletions
|
@ -76,6 +76,11 @@ function processHostCheck($conn, $db, $xml, $trans) {
|
||||||
foreach ($hosts as $host) {
|
foreach ($hosts as $host) {
|
||||||
$host = (string)$host;
|
$host = (string)$host;
|
||||||
|
|
||||||
|
if (preg_match('/^\.[a-z]{2,}$/i', $host) || preg_match('/^[a-z]{2,}$/i', $host)) {
|
||||||
|
sendEppError($conn, $db, 2306, 'Host name must be fully qualified (FQDN)', $clTRID, $trans);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Validation for host name
|
// Validation for host name
|
||||||
if (!validateHostName($host)) {
|
if (!validateHostName($host)) {
|
||||||
sendEppError($conn, $db, 2005, 'Invalid host name', $clTRID, $trans);
|
sendEppError($conn, $db, 2005, 'Invalid host name', $clTRID, $trans);
|
||||||
|
|
|
@ -71,7 +71,7 @@ function processContactCreate($conn, $db, $xml, $clid, $database_type, $trans) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($postalInfoIntOrg) {
|
if ($postalInfoIntOrg) {
|
||||||
if (preg_match('/(^\-)|(^\,)|(^\.)|(\-\-)|(\,\,)|(\.\.)|(\-$)/', $postalInfoIntOrg) || !preg_match('/^[a-zA-Z0-9\-\&\,\.\/\s]{5,}$/', $postalInfoIntOrg)) {
|
if (preg_match('/(^\-)|(^\,)|(^\.)|(\-\-)|(\,\,)|(\.\.)|(\-$)/', $postalInfoIntOrg) || !preg_match('/^[a-zA-Z0-9\-\'\&\,\.\/\s]{5,}$/', $postalInfoIntOrg)) {
|
||||||
sendEppError($conn, $db, 2005, 'Invalid contact:org', $clTRID, $trans);
|
sendEppError($conn, $db, 2005, 'Invalid contact:org', $clTRID, $trans);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -213,6 +213,10 @@ function processContactCreate($conn, $db, $xml, $clid, $database_type, $trans) {
|
||||||
|
|
||||||
$contactCreate = $xml->command->create->children('urn:ietf:params:xml:ns:contact-1.0')->create;
|
$contactCreate = $xml->command->create->children('urn:ietf:params:xml:ns:contact-1.0')->create;
|
||||||
|
|
||||||
|
if (isset($contactCreate->voice) && trim((string) $contactCreate->voice) === '') {
|
||||||
|
sendEppError($conn, $db, 2003, 'Voice element must not be empty if provided', $clTRID, $trans);
|
||||||
|
return;
|
||||||
|
}
|
||||||
$voice = (string) $contactCreate->voice;
|
$voice = (string) $contactCreate->voice;
|
||||||
$voice_x = (string) $contactCreate->voice->attributes()->x;
|
$voice_x = (string) $contactCreate->voice->attributes()->x;
|
||||||
if ($voice && (!preg_match('/^\+\d{1,3}\.\d{1,14}$/', $voice) || strlen($voice) > 17)) {
|
if ($voice && (!preg_match('/^\+\d{1,3}\.\d{1,14}$/', $voice) || strlen($voice) > 17)) {
|
||||||
|
@ -422,13 +426,13 @@ function processHostCreate($conn, $db, $xml, $clid, $database_type, $trans) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// v6 IP validation
|
// v6 IP validation
|
||||||
if ($addr_type === 'v6' && !filter_var($addr, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
|
if ($addr_type === 'v6' && !filter_var($addr, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 | FILTER_FLAG_NO_RES_RANGE | FILTER_FLAG_NO_PRIV_RANGE)) {
|
||||||
sendEppError($conn, $db, 2005, 'Invalid host:addr v6', $clTRID, $trans);
|
sendEppError($conn, $db, 2005, 'Invalid host:addr v6', $clTRID, $trans);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// v4 IP validation
|
// v4 IP validation
|
||||||
if ($addr_type !== 'v6' && !filter_var($addr, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
|
if ($addr_type !== 'v6' && !filter_var($addr, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_RES_RANGE | FILTER_FLAG_NO_PRIV_RANGE)) {
|
||||||
sendEppError($conn, $db, 2005, 'Invalid host:addr v4', $clTRID, $trans);
|
sendEppError($conn, $db, 2005, 'Invalid host:addr v4', $clTRID, $trans);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -461,7 +465,7 @@ function processHostCreate($conn, $db, $xml, $clid, $database_type, $trans) {
|
||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
|
|
||||||
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
|
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||||
if (strpos($hostName, $row['name']) !== false) {
|
if (preg_match('/\.' . preg_quote($row['name'], '/') . '$/i', $hostName)) {
|
||||||
$domain_exist = true;
|
$domain_exist = true;
|
||||||
$clid_domain = $row['clid'];
|
$clid_domain = $row['clid'];
|
||||||
$superordinate_dom = $row['id'];
|
$superordinate_dom = $row['id'];
|
||||||
|
@ -533,6 +537,36 @@ function processHostCreate($conn, $db, $xml, $clid, $database_type, $trans) {
|
||||||
sendEppResponse($conn, $xml);
|
sendEppResponse($conn, $xml);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
$parts = explode('.', $hostName, 2);
|
||||||
|
$superordinate = $parts[1] ?? null;
|
||||||
|
|
||||||
|
if (!$superordinate) {
|
||||||
|
sendEppError($conn, $db, 2005, 'Invalid host:name format', $clTRID, $trans);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if domain exists
|
||||||
|
$stmt = $db->prepare("SELECT id FROM domain WHERE name = :name LIMIT 1");
|
||||||
|
$stmt->execute([':name' => $superordinate]);
|
||||||
|
$domain_id = $stmt->fetchColumn();
|
||||||
|
$stmt->closeCursor();
|
||||||
|
|
||||||
|
if (!$domain_id) {
|
||||||
|
sendEppError($conn, $db, 2303, 'Superordinate domain does not exist for host:name', $clTRID, $trans);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the domain belongs to same registrar
|
||||||
|
$stmt = $db->prepare("SELECT clid FROM domain WHERE name = :name LIMIT 1");
|
||||||
|
$stmt->execute([':name' => $superordinate]);
|
||||||
|
$domain_clid = $stmt->fetchColumn();
|
||||||
|
$stmt->closeCursor();
|
||||||
|
|
||||||
|
if ($clid != $domain_clid) {
|
||||||
|
sendEppError($conn, $db, 2201, 'The superordinate domain belongs to another registrar', $clTRID, $trans);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$stmt = $db->prepare("INSERT INTO host (name,clid,crid,crdate) VALUES(?,?,?,CURRENT_TIMESTAMP(3))");
|
$stmt = $db->prepare("INSERT INTO host (name,clid,crid,crdate) VALUES(?,?,?,CURRENT_TIMESTAMP(3))");
|
||||||
$stmt->execute([$hostName, $clid, $clid]);
|
$stmt->execute([$hostName, $clid, $clid]);
|
||||||
|
|
||||||
|
@ -588,21 +622,32 @@ function processDomainCreate($conn, $db, $xml, $clid, $database_type, $trans, $m
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($launch_extension_enabled && isset($launch_create)) {
|
if ($launch_extension_enabled && isset($launch_create)) {
|
||||||
|
$xml->registerXPathNamespace('launch', 'urn:ietf:params:xml:ns:launch-1.0');
|
||||||
|
$xml->registerXPathNamespace('signedMark', 'urn:ietf:params:xml:ns:signedMark-1.0');
|
||||||
|
|
||||||
$launch_phase_node = $launch_create->xpath('launch:phase')[0] ?? null;
|
$launch_phase_node = $launch_create->xpath('launch:phase')[0] ?? null;
|
||||||
$launch_phase = $launch_phase_node ? (string)$launch_phase_node : null;
|
$launch_phase = $launch_phase_node ? (string)$launch_phase_node : null;
|
||||||
$launch_phase_name = $launch_phase_node ? (string)$launch_phase_node['name'] : null;
|
$launch_phase_name = $launch_phase_node ? (string)$launch_phase_node['name'] : null;
|
||||||
$smd_encodedSignedMark = $launch_create->xpath('smd:encodedSignedMark')[0] ?? null;
|
|
||||||
$launch_notice = $launch_create->xpath('launch:notice')[0] ?? null;
|
$xpath = '//*[namespace-uri()="urn:ietf:params:xml:ns:signedMark-1.0" and local-name()="encodedSignedMark"]';
|
||||||
$launch_noticeID = $launch_notice ? (string) $launch_notice->xpath('launch:noticeID')[0] ?? null : null;
|
$smd_encodedSignedMark = $xml->xpath($xpath)[0] ?? null;
|
||||||
$launch_notAfter = $launch_notice ? (string) $launch_notice->xpath('launch:notAfter')[0] ?? null : null;
|
$smd_encodedSignedMark = $smd_encodedSignedMark ? preg_replace('/\s+/', '', (string)$smd_encodedSignedMark) : null;
|
||||||
$launch_acceptedDate = $launch_notice ? (string) $launch_notice->xpath('launch:acceptedDate')[0] ?? null : null;
|
|
||||||
|
$launch_notice_exists = $xml->xpath('//launch:notice');
|
||||||
|
if (!empty($launch_notice_exists)) {
|
||||||
|
$launch_noticeID = (string) ($xml->xpath('//launch:noticeID')[0] ?? '');
|
||||||
|
$launch_notAfter = (string) ($xml->xpath('//launch:notAfter')[0] ?? '');
|
||||||
|
$launch_acceptedDate = (string) ($xml->xpath('//launch:acceptedDate')[0] ?? '');
|
||||||
|
} else {
|
||||||
|
$launch_noticeID = $launch_notAfter = $launch_acceptedDate = null;
|
||||||
|
}
|
||||||
|
|
||||||
// Validate and handle each specific case
|
// Validate and handle each specific case
|
||||||
if ($launch_phase === 'sunrise' && $smd_encodedSignedMark) {
|
if ($launch_phase === 'sunrise' && $smd_encodedSignedMark) {
|
||||||
// Parse and validate SMD encoded signed mark later
|
// Parse and validate SMD encoded signed mark later
|
||||||
} elseif ($launch_phase === 'claims') {
|
} elseif ($launch_phase === 'claims') {
|
||||||
// Check for missing notice elements and validate dates
|
// Check for missing notice elements and validate dates
|
||||||
if (!$launch_notice || !$launch_noticeID || !$launch_notAfter || !$launch_acceptedDate) {
|
if (!$launch_notice_exists || !$launch_noticeID || !$launch_notAfter || !$launch_acceptedDate) {
|
||||||
sendEppError($conn, $db, 2003, 'Missing required elements in claims phase', $clTRID, $trans);
|
sendEppError($conn, $db, 2003, 'Missing required elements in claims phase', $clTRID, $trans);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1033,12 +1078,12 @@ function processDomainCreate($conn, $db, $xml, $clid, $database_type, $trans, $m
|
||||||
$addr_type = (string) ($node['ip'] ?? 'v4');
|
$addr_type = (string) ($node['ip'] ?? 'v4');
|
||||||
|
|
||||||
if ($addr_type == 'v6') {
|
if ($addr_type == 'v6') {
|
||||||
if (!filter_var($hostAddr, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
|
if (!filter_var($hostAddr, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 | FILTER_FLAG_NO_RES_RANGE | FILTER_FLAG_NO_PRIV_RANGE)) {
|
||||||
sendEppError($conn, $db, 2005, 'Invalid domain:hostAddr v6', $clTRID, $trans);
|
sendEppError($conn, $db, 2005, 'Invalid domain:hostAddr v6', $clTRID, $trans);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!filter_var($hostAddr, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) || $hostAddr === '127.0.0.1') {
|
if (!filter_var($hostAddr, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_RES_RANGE | FILTER_FLAG_NO_PRIV_RANGE) || $hostAddr === '127.0.0.1') {
|
||||||
sendEppError($conn, $db, 2005, 'Invalid domain:hostAddr v4', $clTRID, $trans);
|
sendEppError($conn, $db, 2005, 'Invalid domain:hostAddr v4', $clTRID, $trans);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1111,12 +1156,12 @@ function processDomainCreate($conn, $db, $xml, $clid, $database_type, $trans, $m
|
||||||
$addr_type = isset($node['ip']) ? (string) $node['ip'] : 'v4';
|
$addr_type = isset($node['ip']) ? (string) $node['ip'] : 'v4';
|
||||||
|
|
||||||
if ($addr_type === 'v6') {
|
if ($addr_type === 'v6') {
|
||||||
if (!filter_var($hostAddr, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
|
if (!filter_var($hostAddr, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 | FILTER_FLAG_NO_RES_RANGE | FILTER_FLAG_NO_PRIV_RANGE)) {
|
||||||
sendEppError($conn, $db, 2005, 'Invalid domain:hostAddr v6', $clTRID, $trans);
|
sendEppError($conn, $db, 2005, 'Invalid domain:hostAddr v6', $clTRID, $trans);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!filter_var($hostAddr, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) || $hostAddr === '127.0.0.1') {
|
if (!filter_var($hostAddr, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_RES_RANGE | FILTER_FLAG_NO_PRIV_RANGE) || $hostAddr === '127.0.0.1') {
|
||||||
sendEppError($conn, $db, 2005, 'Invalid domain:hostAddr v4', $clTRID, $trans);
|
sendEppError($conn, $db, 2005, 'Invalid domain:hostAddr v4', $clTRID, $trans);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
function processContactInfo($conn, $db, $xml, $trans) {
|
function processContactInfo($conn, $db, $xml, $clid, $trans) {
|
||||||
$contactID = (string) $xml->command->info->children('urn:ietf:params:xml:ns:contact-1.0')->info->{'id'};
|
$contactID = (string) $xml->command->info->children('urn:ietf:params:xml:ns:contact-1.0')->info->{'id'};
|
||||||
$clTRID = (string) $xml->command->clTRID;
|
$clTRID = (string) $xml->command->clTRID;
|
||||||
|
|
||||||
|
@ -38,6 +38,12 @@ function processContactInfo($conn, $db, $xml, $trans) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$clid = getClid($db, $clid);
|
||||||
|
if ($clid !== $contact[0]['clid']) {
|
||||||
|
sendEppError($conn, $db, 2201, 'Client is not the sponsor of the contact object', $clTRID, $trans);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Extract the first row for contact data
|
// Extract the first row for contact data
|
||||||
$contactRow = $contact[0];
|
$contactRow = $contact[0];
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,7 @@ function processContactUpdate($conn, $db, $xml, $clid, $database_type, $trans) {
|
||||||
$stmt->closeCursor();
|
$stmt->closeCursor();
|
||||||
|
|
||||||
if ($contactRem) {
|
if ($contactRem) {
|
||||||
$statusList = $xml->xpath('//contact:status/@s', $contactRem);
|
$statusList = $contactRem[0]->xpath('contact:status/@s');
|
||||||
|
|
||||||
if (count($statusList) == 0) {
|
if (count($statusList) == 0) {
|
||||||
sendEppError($conn, $db, 2005, 'At least one status element MUST be present', $clTRID, $trans);
|
sendEppError($conn, $db, 2005, 'At least one status element MUST be present', $clTRID, $trans);
|
||||||
|
@ -80,7 +80,7 @@ function processContactUpdate($conn, $db, $xml, $clid, $database_type, $trans) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($contactAdd) {
|
if ($contactAdd) {
|
||||||
$statusList = $xml->xpath('//contact:status/@s', $contactAdd);
|
$statusList = $contactAdd[0]->xpath('contact:status/@s');
|
||||||
|
|
||||||
if (count($statusList) == 0) {
|
if (count($statusList) == 0) {
|
||||||
sendEppError($conn, $db, 2005, 'At least one status element MUST be present', $clTRID, $trans);
|
sendEppError($conn, $db, 2005, 'At least one status element MUST be present', $clTRID, $trans);
|
||||||
|
@ -94,7 +94,7 @@ function processContactUpdate($conn, $db, $xml, $clid, $database_type, $trans) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count($xml->xpath('contact:status[@s="' . $status . '"]', $contactRem)) == 0) {
|
if (!$contactRem || count($contactRem[0]->xpath('contact:status[@s="' . $status . '"]')) == 0) {
|
||||||
$stmt = $db->prepare("SELECT id FROM contact_status WHERE contact_id = :contact_id AND status = :status LIMIT 1");
|
$stmt = $db->prepare("SELECT id FROM contact_status WHERE contact_id = :contact_id AND status = :status LIMIT 1");
|
||||||
$stmt->execute([':contact_id' => $contact_id, ':status' => $status]);
|
$stmt->execute([':contact_id' => $contact_id, ':status' => $status]);
|
||||||
$contactStatusId = $stmt->fetchColumn();
|
$contactStatusId = $stmt->fetchColumn();
|
||||||
|
@ -113,6 +113,17 @@ function processContactUpdate($conn, $db, $xml, $clid, $database_type, $trans) {
|
||||||
$postalInfoInt = null;
|
$postalInfoInt = null;
|
||||||
$postalInfoLoc = null;
|
$postalInfoLoc = null;
|
||||||
|
|
||||||
|
$postalInfoAllNodes = $xml->xpath('//contact:postalInfo');
|
||||||
|
|
||||||
|
foreach ($postalInfoAllNodes as $node) {
|
||||||
|
$typeAttr = (string) $node['type'];
|
||||||
|
|
||||||
|
if ($typeAttr !== 'int' && $typeAttr !== 'loc') {
|
||||||
|
sendEppError($conn, $db, 2003, 'Invalid postalInfo type attribute: must be "int" or "loc"', $clTRID, $trans);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$postalInfoIntNodes = $xml->xpath("//contact:postalInfo[@type='int']");
|
$postalInfoIntNodes = $xml->xpath("//contact:postalInfo[@type='int']");
|
||||||
|
|
||||||
if (count($postalInfoIntNodes) > 0) {
|
if (count($postalInfoIntNodes) > 0) {
|
||||||
|
@ -150,40 +161,64 @@ function processContactUpdate($conn, $db, $xml, $clid, $database_type, $trans) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (preg_match('/(^\-)|(^\,)|(^\.)|(\-\-)|(\,\,)|(\.\.)|(\-$)/', $postalInfoIntName) || !preg_match('/^[a-zA-Z0-9\-\&\,\.\/\s]{5,}$/', $postalInfoIntName)) {
|
if (
|
||||||
|
preg_match('/(^\-)|(^\,)|(^\.)|(\-\-)|(\,\,)|(\.\.)|(\-$)/', $postalInfoIntName) ||
|
||||||
|
!preg_match('/^[a-zA-Z0-9\-\&\,\.\/\s]{5,}$/', $postalInfoIntName) ||
|
||||||
|
strlen($postalInfoIntName) > 255
|
||||||
|
) {
|
||||||
sendEppError($conn, $db, 2005, 'Invalid contact:name', $clTRID, $trans);
|
sendEppError($conn, $db, 2005, 'Invalid contact:name', $clTRID, $trans);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($postalInfoIntOrg) {
|
if ($postalInfoIntOrg) {
|
||||||
if (preg_match('/(^\-)|(^\,)|(^\.)|(\-\-)|(\,\,)|(\.\.)|(\-$)/', $postalInfoIntOrg) || !preg_match('/^[a-zA-Z0-9\-\&\,\.\/\s]{5,}$/', $postalInfoIntOrg)) {
|
if (
|
||||||
|
preg_match('/(^\-)|(^\,)|(^\.)|(\-\-)|(\,\,)|(\.\.)|(\-$)/', $postalInfoIntOrg) ||
|
||||||
|
!preg_match('/^[a-zA-Z0-9\-\&\,\.\/\s]{5,}$/', $postalInfoIntOrg) ||
|
||||||
|
strlen($postalInfoIntOrg) > 255
|
||||||
|
) {
|
||||||
sendEppError($conn, $db, 2005, 'Invalid contact:org', $clTRID, $trans);
|
sendEppError($conn, $db, 2005, 'Invalid contact:org', $clTRID, $trans);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($postalInfoIntStreet1) {
|
if ($postalInfoIntStreet1) {
|
||||||
if (preg_match('/(^\-)|(^\,)|(^\.)|(\-\-)|(\,\,)|(\.\.)|(\-$)/', $postalInfoIntStreet1) || !preg_match('/^[a-zA-Z0-9\-\&\,\.\/\s]{5,}$/', $postalInfoIntStreet1)) {
|
if (
|
||||||
|
preg_match('/(^\-)|(^\,)|(^\.)|(\-\-)|(\,\,)|(\.\.)|(\-$)/', $postalInfoIntStreet1) ||
|
||||||
|
!preg_match('/^[a-zA-Z0-9\-\&\,\.\/\s]{5,}$/', $postalInfoIntStreet1) ||
|
||||||
|
strlen($postalInfoIntStreet1) > 255
|
||||||
|
) {
|
||||||
sendEppError($conn, $db, 2005, 'Invalid contact:street', $clTRID, $trans);
|
sendEppError($conn, $db, 2005, 'Invalid contact:street', $clTRID, $trans);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($postalInfoIntStreet2) {
|
if ($postalInfoIntStreet2) {
|
||||||
if (preg_match('/(^\-)|(^\,)|(^\.)|(\-\-)|(\,\,)|(\.\.)|(\-$)/', $postalInfoIntStreet2) || !preg_match('/^[a-zA-Z0-9\-\&\,\.\/\s]{5,}$/', $postalInfoIntStreet2)) {
|
if (
|
||||||
|
preg_match('/(^\-)|(^\,)|(^\.)|(\-\-)|(\,\,)|(\.\.)|(\-$)/', $postalInfoIntStreet2) ||
|
||||||
|
!preg_match('/^[a-zA-Z0-9\-\&\,\.\/\s]{5,}$/', $postalInfoIntStreet2) ||
|
||||||
|
strlen($postalInfoIntStreet2) > 255
|
||||||
|
) {
|
||||||
sendEppError($conn, $db, 2005, 'Invalid contact:street', $clTRID, $trans);
|
sendEppError($conn, $db, 2005, 'Invalid contact:street', $clTRID, $trans);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($postalInfoIntStreet3) {
|
if ($postalInfoIntStreet3) {
|
||||||
if (preg_match('/(^\-)|(^\,)|(^\.)|(\-\-)|(\,\,)|(\.\.)|(\-$)/', $postalInfoIntStreet3) || !preg_match('/^[a-zA-Z0-9\-\&\,\.\/\s]{5,}$/', $postalInfoIntStreet3)) {
|
if (
|
||||||
|
preg_match('/(^\-)|(^\,)|(^\.)|(\-\-)|(\,\,)|(\.\.)|(\-$)/', $postalInfoIntStreet3) ||
|
||||||
|
!preg_match('/^[a-zA-Z0-9\-\&\,\.\/\s]{5,}$/', $postalInfoIntStreet3) ||
|
||||||
|
strlen($postalInfoIntStreet3) > 255
|
||||||
|
) {
|
||||||
sendEppError($conn, $db, 2005, 'Invalid contact:street', $clTRID, $trans);
|
sendEppError($conn, $db, 2005, 'Invalid contact:street', $clTRID, $trans);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (preg_match('/(^\-)|(^\.)|(\-\-)|(\.\.)|(\.\-)|(\-\.)|(\-$)|(\.$)/', $postalInfoIntCity) || !preg_match('/^[a-z][a-z\-\.\'\s]{2,}$/i', $postalInfoIntCity)) {
|
if (
|
||||||
|
preg_match('/(^\-)|(^\.)|(\-\-)|(\.\.)|(\.\-)|(\-\.)|(\-$)|(\.$)/', $postalInfoIntCity) ||
|
||||||
|
!preg_match('/^[a-z][a-z\-\.\'\s]{2,}$/i', $postalInfoIntCity) ||
|
||||||
|
strlen($postalInfoIntCity) > 255
|
||||||
|
) {
|
||||||
sendEppError($conn, $db, 2005, 'Invalid contact:city', $clTRID, $trans);
|
sendEppError($conn, $db, 2005, 'Invalid contact:city', $clTRID, $trans);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -466,6 +501,17 @@ function processContactUpdate($conn, $db, $xml, $clid, $database_type, $trans) {
|
||||||
$e_authInfo_ext = $stmt_ext->fetchColumn();
|
$e_authInfo_ext = $stmt_ext->fetchColumn();
|
||||||
$stmt_ext->closeCursor();
|
$stmt_ext->closeCursor();
|
||||||
|
|
||||||
|
$postalInfoAllNodes = $xml->xpath('//contact:postalInfo');
|
||||||
|
|
||||||
|
foreach ($postalInfoAllNodes as $node) {
|
||||||
|
$typeAttr = (string) $node['type'];
|
||||||
|
|
||||||
|
if ($typeAttr !== 'int' && $typeAttr !== 'loc') {
|
||||||
|
sendEppError($conn, $db, 2003, 'Invalid postalInfo type attribute: must be "int" or "loc"', $clTRID, $trans);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$postalInfo_int = $xml->xpath("//contact:postalInfo[@type='int']")[0] ?? null;
|
$postalInfo_int = $xml->xpath("//contact:postalInfo[@type='int']")[0] ?? null;
|
||||||
if ($postalInfoInt) {
|
if ($postalInfoInt) {
|
||||||
$int_name = (string)($postalInfo_int->xpath("contact:name")[0] ?? "");
|
$int_name = (string)($postalInfo_int->xpath("contact:name")[0] ?? "");
|
||||||
|
@ -783,11 +829,15 @@ function processHostUpdate($conn, $db, $xml, $clid, $database_type, $trans) {
|
||||||
|
|
||||||
foreach ($addr_list as $node) {
|
foreach ($addr_list as $node) {
|
||||||
$addr = (string) $node;
|
$addr = (string) $node;
|
||||||
$addr_type = $node->attributes()->ip ?? 'v4';
|
$addr_type = (string) ($node->attributes()->ip ?? 'v4');
|
||||||
|
if (!in_array($addr_type, ['v4', 'v6'])) {
|
||||||
|
sendEppError($conn, $db, 2005, 'host:addr ip attribute must be "v4" or "v6"', $clTRID, $trans);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ($addr_type == 'v6') {
|
if ($addr_type == 'v6') {
|
||||||
// IPv6 validation and normalization
|
// IPv6 validation and normalization
|
||||||
if (filter_var($addr, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
|
if (filter_var($addr, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 | FILTER_FLAG_NO_RES_RANGE | FILTER_FLAG_NO_PRIV_RANGE)) {
|
||||||
$addr = normalize_v6_address($addr);
|
$addr = normalize_v6_address($addr);
|
||||||
$stmt = $db->prepare("SELECT id FROM host_addr WHERE host_id = ? AND addr = ? AND ip = '6' LIMIT 1");
|
$stmt = $db->prepare("SELECT id FROM host_addr WHERE host_id = ? AND addr = ? AND ip = '6' LIMIT 1");
|
||||||
$stmt->execute([$hostId, $addr]);
|
$stmt->execute([$hostId, $addr]);
|
||||||
|
@ -804,7 +854,7 @@ function processHostUpdate($conn, $db, $xml, $clid, $database_type, $trans) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// IPv4 validation and normalization
|
// IPv4 validation and normalization
|
||||||
if (filter_var($addr, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
|
if (filter_var($addr, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_RES_RANGE | FILTER_FLAG_NO_PRIV_RANGE)) {
|
||||||
$addr = normalize_v4_address($addr);
|
$addr = normalize_v4_address($addr);
|
||||||
$stmt = $db->prepare("SELECT id FROM host_addr WHERE host_id = ? AND addr = ? AND ip = '4' LIMIT 1");
|
$stmt = $db->prepare("SELECT id FROM host_addr WHERE host_id = ? AND addr = ? AND ip = '4' LIMIT 1");
|
||||||
$stmt->execute([$hostId, $addr]);
|
$stmt->execute([$hostId, $addr]);
|
||||||
|
@ -1023,7 +1073,7 @@ function processDomainUpdate($conn, $db, $xml, $clid, $database_type, $trans) {
|
||||||
}
|
}
|
||||||
|
|
||||||
$clid = getClid($db, $clid);
|
$clid = getClid($db, $clid);
|
||||||
if ($clid != $row['clid']) {
|
if ($clid !== $row['clid']) {
|
||||||
sendEppError($conn, $db, 2201, 'You do not have privileges to modify a domain name that belongs to another registrar', $clTRID, $trans);
|
sendEppError($conn, $db, 2201, 'You do not have privileges to modify a domain name that belongs to another registrar', $clTRID, $trans);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1195,6 +1245,16 @@ function processDomainUpdate($conn, $db, $xml, $clid, $database_type, $trans) {
|
||||||
if (count($hostObjList) > 0) {
|
if (count($hostObjList) > 0) {
|
||||||
foreach ($hostObjList as $node) {
|
foreach ($hostObjList as $node) {
|
||||||
$hostObj = strtoupper((string)$node);
|
$hostObj = strtoupper((string)$node);
|
||||||
|
$stmt = $db->prepare("SELECT id FROM host WHERE name = ? LIMIT 1");
|
||||||
|
$stmt->execute([$hostObj]);
|
||||||
|
$hostExists = $stmt->fetchColumn();
|
||||||
|
$stmt->closeCursor();
|
||||||
|
|
||||||
|
if (!$hostExists) {
|
||||||
|
sendEppError($conn, $db, 2303, "domain:hostObj $hostObj does not exist", $clTRID, $trans);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (preg_match('/[^A-Z0-9\.\-]/', $hostObj) || preg_match('/^-|^\.-|-\.-|^-|-$/', $hostObj)) {
|
if (preg_match('/[^A-Z0-9\.\-]/', $hostObj) || preg_match('/^-|^\.-|-\.-|^-|-$/', $hostObj)) {
|
||||||
sendEppError($conn, $db, 2005, 'Invalid domain:hostObj', $clTRID, $trans);
|
sendEppError($conn, $db, 2005, 'Invalid domain:hostObj', $clTRID, $trans);
|
||||||
return;
|
return;
|
||||||
|
@ -1269,12 +1329,12 @@ function processDomainUpdate($conn, $db, $xml, $clid, $database_type, $trans) {
|
||||||
$addrType = (string)$addrType;
|
$addrType = (string)$addrType;
|
||||||
|
|
||||||
if ($addrType === 'v6') {
|
if ($addrType === 'v6') {
|
||||||
if (!filter_var($hostAddr, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
|
if (!filter_var($hostAddr, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 | FILTER_FLAG_NO_RES_RANGE | FILTER_FLAG_NO_PRIV_RANGE)) {
|
||||||
sendEppError($conn, $db, 2005, 'Invalid domain:hostAddr v6', $clTRID, $trans);
|
sendEppError($conn, $db, 2005, 'Invalid domain:hostAddr v6', $clTRID, $trans);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!filter_var($hostAddr, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) || $hostAddr == '127.0.0.1') {
|
if (!filter_var($hostAddr, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_RES_RANGE | FILTER_FLAG_NO_PRIV_RANGE) || $hostAddr == '127.0.0.1') {
|
||||||
sendEppError($conn, $db, 2005, 'Invalid domain:hostAddr v4', $clTRID, $trans);
|
sendEppError($conn, $db, 2005, 'Invalid domain:hostAddr v4', $clTRID, $trans);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1435,6 +1495,9 @@ function processDomainUpdate($conn, $db, $xml, $clid, $database_type, $trans) {
|
||||||
sendEppError($conn, $db, 2400, 'Database error', $clTRID, $trans);
|
sendEppError($conn, $db, 2400, 'Database error', $clTRID, $trans);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
sendEppError($conn, $db, 2303, "hostObj $hostObj does not exist", $clTRID, $trans);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1501,6 +1564,19 @@ function processDomainUpdate($conn, $db, $xml, $clid, $database_type, $trans) {
|
||||||
foreach ($status_list as $node) {
|
foreach ($status_list as $node) {
|
||||||
$status = (string) $node;
|
$status = (string) $node;
|
||||||
|
|
||||||
|
$stmt = $db->prepare("SELECT 1 FROM domain_status WHERE domain_id = :domain_id AND status = :status LIMIT 1");
|
||||||
|
$stmt->execute([
|
||||||
|
':domain_id' => $domain_id,
|
||||||
|
':status' => $status
|
||||||
|
]);
|
||||||
|
$exists = $stmt->fetchColumn();
|
||||||
|
$stmt->closeCursor();
|
||||||
|
|
||||||
|
if (!$exists) {
|
||||||
|
sendEppError($conn, $db, 2303, "Cannot remove status '$status': not present on domain", $clTRID, $trans);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$stmt = $db->prepare("DELETE FROM domain_status WHERE domain_id = :domain_id AND status = :status");
|
$stmt = $db->prepare("DELETE FROM domain_status WHERE domain_id = :domain_id AND status = :status");
|
||||||
$stmt->bindParam(':domain_id', $domain_id, PDO::PARAM_INT);
|
$stmt->bindParam(':domain_id', $domain_id, PDO::PARAM_INT);
|
||||||
$stmt->bindParam(':status', $status, PDO::PARAM_STR);
|
$stmt->bindParam(':status', $status, PDO::PARAM_STR);
|
||||||
|
@ -2010,6 +2086,20 @@ function processDomainUpdate($conn, $db, $xml, $clid, $database_type, $trans) {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// Check if DS record exists before attempting to delete
|
||||||
|
$stmt = $db->prepare("SELECT COUNT(*) FROM secdns WHERE domain_id = :domain_id AND keytag = :keyTag AND alg = :alg AND digesttype = :digestType AND digest = :digest");
|
||||||
|
$stmt->execute([
|
||||||
|
':domain_id' => $domain_id,
|
||||||
|
':keyTag' => $keyTag,
|
||||||
|
':alg' => $alg,
|
||||||
|
':digestType' => $digestType,
|
||||||
|
':digest' => $digest
|
||||||
|
]);
|
||||||
|
if ($stmt->fetchColumn() == 0) {
|
||||||
|
sendEppError($conn, $db, 2306, 'DS record not found for removal', $clTRID, $trans);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$stmt = $db->prepare("DELETE FROM secdns WHERE domain_id = :domain_id AND keytag = :keyTag AND alg = :alg AND digesttype = :digestType AND digest = :digest");
|
$stmt = $db->prepare("DELETE FROM secdns WHERE domain_id = :domain_id AND keytag = :keyTag AND alg = :alg AND digesttype = :digestType AND digest = :digest");
|
||||||
$stmt->execute([
|
$stmt->execute([
|
||||||
':domain_id' => $domain_id,
|
':domain_id' => $domain_id,
|
||||||
|
@ -2060,6 +2150,20 @@ function processDomainUpdate($conn, $db, $xml, $clid, $database_type, $trans) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if keyData exists before attempting to delete
|
||||||
|
$stmt = $db->prepare("SELECT COUNT(*) FROM secdns WHERE domain_id = :domain_id AND flags = :flags AND protocol = :protocol AND keydata_alg = :algKeyData AND pubkey = :pubKey");
|
||||||
|
$stmt->execute([
|
||||||
|
':domain_id' => $domain_id,
|
||||||
|
':flags' => $flags,
|
||||||
|
':protocol' => $protocol,
|
||||||
|
':algKeyData' => $algKeyData,
|
||||||
|
':pubKey' => $pubKey
|
||||||
|
]);
|
||||||
|
if ($stmt->fetchColumn() == 0) {
|
||||||
|
sendEppError($conn, $db, 2306, 'KeyData not found for removal', $clTRID, $trans);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$stmt = $db->prepare("DELETE FROM secdns WHERE domain_id = :domain_id AND flags = :flags AND protocol = :protocol AND algKeyData = :algKeyData AND pubKey = :pubKey");
|
$stmt = $db->prepare("DELETE FROM secdns WHERE domain_id = :domain_id AND flags = :flags AND protocol = :protocol AND algKeyData = :algKeyData AND pubKey = :pubKey");
|
||||||
$stmt->execute([
|
$stmt->execute([
|
||||||
|
@ -2089,10 +2193,48 @@ function processDomainUpdate($conn, $db, $xml, $clid, $database_type, $trans) {
|
||||||
if ($secDNSDataSet) {
|
if ($secDNSDataSet) {
|
||||||
foreach ($secDNSDataSet as $secDNSData) {
|
foreach ($secDNSDataSet as $secDNSData) {
|
||||||
// Extract dsData elements
|
// Extract dsData elements
|
||||||
$keyTag = (int) $secDNSData->xpath('secDNS:keyTag')[0] ?? null;
|
$keyTagNode = $secDNSData->xpath('secDNS:keyTag')[0] ?? null;
|
||||||
$alg = (int) $secDNSData->xpath('secDNS:alg')[0] ?? null;
|
if (!isset($keyTagNode) || trim((string)$keyTagNode) === '') {
|
||||||
$digestType = (int) $secDNSData->xpath('secDNS:digestType')[0] ?? null;
|
sendEppError($conn, $db, 2005, 'Missing or empty keyTag', $clTRID, $trans);
|
||||||
$digest = (string) $secDNSData->xpath('secDNS:digest')[0] ?? null;
|
return;
|
||||||
|
}
|
||||||
|
$keyTag = (int) $keyTagNode;
|
||||||
|
|
||||||
|
$algNode = $secDNSData->xpath('secDNS:alg')[0] ?? null;
|
||||||
|
if (!isset($algNode) || trim((string)$algNode) === '') {
|
||||||
|
sendEppError($conn, $db, 2005, 'Missing or empty algorithm', $clTRID, $trans);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$alg = (int) $algNode;
|
||||||
|
$validAlgorithms = [8, 13, 14, 15, 16];
|
||||||
|
if (!in_array($alg, $validAlgorithms)) {
|
||||||
|
sendEppError($conn, $db, 2006, 'Invalid algorithm', $clTRID, $trans);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$digestTypeNode = $secDNSData->xpath('secDNS:digestType')[0] ?? null;
|
||||||
|
if (!isset($digestTypeNode) || trim((string)$digestTypeNode) === '') {
|
||||||
|
sendEppError($conn, $db, 2005, 'Missing or empty digestType', $clTRID, $trans);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$digestType = (int) $digestTypeNode;
|
||||||
|
$validDigests = [2 => 64, 4 => 96]; // SHA-256 and SHA-384
|
||||||
|
if (!array_key_exists($digestType, $validDigests)) {
|
||||||
|
sendEppError($conn, $db, 2006, 'Unsupported digestType', $clTRID, $trans);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$digestNode = $secDNSData->xpath('secDNS:digest')[0] ?? null;
|
||||||
|
if (!isset($digestNode) || trim((string)$digestNode) === '') {
|
||||||
|
sendEppError($conn, $db, 2005, 'Missing or empty digest', $clTRID, $trans);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$digest = (string) $digestNode;
|
||||||
|
if (strlen($digest) !== $validDigests[$digestType] || !ctype_xdigit($digest)) {
|
||||||
|
sendEppError($conn, $db, 2006, 'Invalid digest length or format', $clTRID, $trans);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$maxSigLife = $secDNSData->xpath('secDNS:maxSigLife') ? (int) $secDNSData->xpath('secDNS:maxSigLife')[0] : null;
|
$maxSigLife = $secDNSData->xpath('secDNS:maxSigLife') ? (int) $secDNSData->xpath('secDNS:maxSigLife')[0] : null;
|
||||||
|
|
||||||
// Data sanity checks
|
// Data sanity checks
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue