diff --git a/epp/src/epp-create.php b/epp/src/epp-create.php index 00fa364..05b4fa5 100644 --- a/epp/src/epp-create.php +++ b/epp/src/epp-create.php @@ -615,6 +615,17 @@ function processDomainCreate($conn, $db, $xml, $clid, $database_type, $trans, $m $stmt->closeCursor(); } + $invalid_domain = validate_label($domainName, $db); + + if ($invalid_domain) { + sendEppError($conn, $db, 2306, 'Invalid domain:name', $clTRID, $trans); + return; + } + + $parts = extractDomainAndTLD($domainName); + $label = $parts['domain']; + $domain_extension = '.' . strtoupper($parts['tld']); + 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'); @@ -622,6 +633,10 @@ function processDomainCreate($conn, $db, $xml, $clid, $database_type, $trans, $m $launch_phase_node = $launch_create->xpath('launch:phase')[0] ?? null; $launch_phase = $launch_phase_node ? (string)$launch_phase_node : null; $launch_phase_name = $launch_phase_node ? (string)$launch_phase_node['name'] : null; + + $noticeid = null; + $notafter = null; + $accepted = null; $xpath = '//*[namespace-uri()="urn:ietf:params:xml:ns:signedMark-1.0" and local-name()="encodedSignedMark"]'; $smd_encodedSignedMark = $xml->xpath($xpath)[0] ?? null; @@ -641,10 +656,16 @@ function processDomainCreate($conn, $db, $xml, $clid, $database_type, $trans, $m // Parse and validate SMD encoded signed mark later } elseif ($launch_phase === 'claims') { // Check for missing notice elements and validate dates - if (!$launch_notice_exists || !$launch_noticeID || !$launch_notAfter || !$launch_acceptedDate) { - sendEppError($conn, $db, 2003, 'Missing required elements in claims phase', $clTRID, $trans); + if (!isset($launch_noticeID) || $launch_noticeID === '' || + !isset($launch_notAfter) || $launch_notAfter === '' || + !isset($launch_acceptedDate) || $launch_acceptedDate === '') { + sendEppError($conn, $db, 2306, "Error creating domain: 'noticeid', 'notafter', or 'accepted' cannot be empty when phaseType is 'claims'", $clTRID, $trans); return; } + + $noticeid = $launch_noticeID; + $notafter = $launch_notAfter; + $accepted = $launch_acceptedDate; // Validate that acceptedDate is before notAfter try { @@ -665,7 +686,15 @@ function processDomainCreate($conn, $db, $xml, $clid, $database_type, $trans, $m return; } - // If all validations pass, continue + $stmt = $db->prepare("SELECT id FROM tmch_claims WHERE domain_label = ? AND claim_key = ? LIMIT 1"); + $stmt->execute([$label, $noticeid]); + $claim_valid = $stmt->fetchColumn(); + $stmt->closeCursor(); + + if (!$claim_valid) { + sendEppError($conn, $db, 2306, 'Invalid or expired claims noticeID for this domain label', $clTRID, $trans); + return; + } } elseif ($launch_phase === 'landrush') { // Continue } elseif ($launch_phase === 'custom') { @@ -681,17 +710,6 @@ function processDomainCreate($conn, $db, $xml, $clid, $database_type, $trans, $m } } - $invalid_domain = validate_label($domainName, $db); - - if ($invalid_domain) { - sendEppError($conn, $db, 2306, 'Invalid domain:name', $clTRID, $trans); - return; - } - - $parts = extractDomainAndTLD($domainName); - $label = $parts['domain']; - $domain_extension = '.' . strtoupper($parts['tld']); - $stmt = $db->prepare("SELECT id FROM domain_tld WHERE UPPER(tld) = ?"); $stmt->execute([$domain_extension]); $tld_id = $stmt->fetchColumn(); @@ -779,23 +797,6 @@ function processDomainCreate($conn, $db, $xml, $clid, $database_type, $trans, $m return; } } - - if ($launch_phase === 'claims') { - if (!isset($launch_noticeID) || $launch_noticeID === '' || - !isset($launch_notAfter) || $launch_notAfter === '' || - !isset($launch_acceptedDate) || $launch_acceptedDate === '') { - sendEppError($conn, $db, 2306, "Error creating domain: 'noticeid', 'notafter', or 'accepted' cannot be empty when phaseType is 'claims'", $clTRID, $trans); - return; - } - - $noticeid = $launch_noticeID; - $notafter = $launch_notAfter; - $accepted = $launch_acceptedDate; - } else { - $noticeid = null; - $notafter = null; - $accepted = null; - } if ($launch_phase === 'sunrise') { if ($smd_encodedSignedMark !== null && $smd_encodedSignedMark !== '') { diff --git a/epp/src/epp-transfer.php b/epp/src/epp-transfer.php index 0f944e0..a8c5d7c 100644 --- a/epp/src/epp-transfer.php +++ b/epp/src/epp-transfer.php @@ -605,6 +605,7 @@ function processDomainTransfer($conn, $db, $xml, $clid, $database_type, $trans) $stmt = $db->prepare("UPDATE domain SET exdate = DATE_ADD(exdate, INTERVAL ? MONTH), lastupdate = CURRENT_TIMESTAMP(3), clid = ?, upid = ?, registrant = ?, trdate = CURRENT_TIMESTAMP(3), trstatus = 'clientApproved', acdate = CURRENT_TIMESTAMP(3), transfer_exdate = NULL, rgpstatus = 'transferPeriod', transferPeriod = ? WHERE id = ?"); $stmt->execute([$date_add, $row["reid"], $clid, $newRegistrantId, $date_add, $domain_id]); + $reid = $row['reid']; $stmt_log = $db->prepare("INSERT INTO error_log (channel, level, level_name, message, context, extra) VALUES (?, ?, ?, ?, ?, ?)"); $stmt_log->execute([ 'manual_transfer', diff --git a/epp/src/helpers.php b/epp/src/helpers.php index fbfd784..78520ab 100644 --- a/epp/src/helpers.php +++ b/epp/src/helpers.php @@ -1060,6 +1060,6 @@ function ipMatches($ip, $cidr) { } function normalizeDatetime($input) { - $dt = DateTime::createFromFormat(DateTime::ATOM, $input); // handles 'T' and 'Z' - return $dt ? $dt->format('Y-m-d H:i:s.v') : null; // .v gives milliseconds + $dt = DateTime::createFromFormat('Y-m-d\TH:i:s.v\Z', $input); + return $dt ? $dt->format('Y-m-d H:i:s.v') : null; } \ No newline at end of file