mirror of
https://github.com/getnamingo/registry.git
synced 2025-07-03 01:23:22 +02:00
DNSSEC validation and secdns extension fully work
This commit is contained in:
parent
161e462dbf
commit
b889d036c2
2 changed files with 261 additions and 91 deletions
|
@ -1047,8 +1047,39 @@ function processDomainCreate($conn, $db, $xml, $clid, $database_type, $trans) {
|
||||||
$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
|
||||||
if (!$keyTag || !$alg || !$digestType || !$digest) {
|
// Validate keyTag
|
||||||
sendEppError($conn, 2005, 'Incomplete or invalid dsData provided', $clTRID);
|
if (!isset($keyTag) || !is_int($keyTag)) {
|
||||||
|
sendEppError($conn, 2005, 'Incomplete keyTag provided', $clTRID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ($keyTag < 0 || $keyTag > 65535) {
|
||||||
|
sendEppError($conn, 2006, 'Invalid keyTag provided', $clTRID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate alg
|
||||||
|
$validAlgorithms = [2, 3, 5, 6, 7, 8, 10, 13, 14, 15, 16];
|
||||||
|
if (!isset($alg) || !in_array($alg, $validAlgorithms)) {
|
||||||
|
sendEppError($conn, 2006, 'Invalid algorithm', $clTRID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate digestType and digest
|
||||||
|
if (!isset($digestType) || !is_int($digestType)) {
|
||||||
|
sendEppError($conn, 2005, 'Invalid digestType', $clTRID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$validDigests = [
|
||||||
|
1 => 40, // SHA-1
|
||||||
|
2 => 64, // SHA-256
|
||||||
|
4 => 96 // SHA-384
|
||||||
|
];
|
||||||
|
if (!isset($validDigests[$digestType])) {
|
||||||
|
sendEppError($conn, 2006, 'Unsupported digestType', $clTRID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!isset($digest) || strlen($digest) != $validDigests[$digestType] || !ctype_xdigit($digest)) {
|
||||||
|
sendEppError($conn, 2006, 'Invalid digest length or format', $clTRID);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1065,8 +1096,28 @@ function processDomainCreate($conn, $db, $xml, $clid, $database_type, $trans) {
|
||||||
$pubKey = (string) $secDNSData->xpath('secDNS:keyData/secDNS:pubKey')[0];
|
$pubKey = (string) $secDNSData->xpath('secDNS:keyData/secDNS:pubKey')[0];
|
||||||
|
|
||||||
// Data sanity checks for keyData
|
// Data sanity checks for keyData
|
||||||
if (!$flags || !$protocol || !$algKeyData || !$pubKey) {
|
// Validate flags
|
||||||
sendEppError($conn, 2005, 'Incomplete or invalid keyData provided', $clTRID);
|
$validFlags = [256, 257];
|
||||||
|
if (isset($flags) && !in_array($flags, $validFlags)) {
|
||||||
|
sendEppError($conn, 2005, 'Invalid flags', $clTRID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate protocol
|
||||||
|
if (isset($protocol) && $protocol != 3) {
|
||||||
|
sendEppError($conn, 2006, 'Invalid protocol', $clTRID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate algKeyData
|
||||||
|
if (isset($algKeyData)) {
|
||||||
|
sendEppError($conn, 2005, 'Invalid algKeyData encoding', $clTRID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate pubKey
|
||||||
|
if (isset($pubKey) && base64_encode(base64_decode($pubKey, true)) !== $pubKey) {
|
||||||
|
sendEppError($conn, 2005, 'Invalid pubKey encoding', $clTRID);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1739,28 +1739,72 @@ function processDomainUpdate($conn, $db, $xml, $clid, $database_type, $trans) {
|
||||||
$secdnsAdds = $xml->xpath('//secDNS:add') ?? [];
|
$secdnsAdds = $xml->xpath('//secDNS:add') ?? [];
|
||||||
$secdnsChg = $xml->xpath('//secDNS:chg')[0] ?? null;
|
$secdnsChg = $xml->xpath('//secDNS:chg')[0] ?? null;
|
||||||
|
|
||||||
|
if (isset($secdnsRems)) {
|
||||||
foreach ($secdnsRems as $secdnsRem) {
|
foreach ($secdnsRems as $secdnsRem) {
|
||||||
$dsDataToRemove = $secdnsRem->xpath('./secDNS:dsData');
|
$dsDataToRemove = $secdnsRem->xpath('./secDNS:dsData');
|
||||||
foreach ($dsDataToRemove as $ds) {
|
foreach ($dsDataToRemove as $ds) {
|
||||||
$keyTag = (int)$ds->keyTag;
|
$keyTag = (int)$ds->xpath('secDNS:keyTag')[0];
|
||||||
$algorithm = (int)$ds->alg;
|
$alg = (int)$ds->xpath('secDNS:alg')[0];
|
||||||
$digestType = (int)$ds->digestType;
|
$digestType = (int)$ds->xpath('secDNS:digestType')[0];
|
||||||
$digest = (string)$ds->digest;
|
$digest = (string)$ds->xpath('secDNS:digest')[0];
|
||||||
|
|
||||||
$stmt = $db->prepare("DELETE FROM secdns WHERE domain_id = :domain_id AND keyTag = :keyTag AND algorithm = :algorithm AND digestType = :digestType AND digest = :digest");
|
// Data sanity checks
|
||||||
|
// Validate keyTag
|
||||||
|
if (!isset($keyTag) || !is_int($keyTag)) {
|
||||||
|
sendEppError($conn, 2005, 'Incomplete keyTag provided', $clTRID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ($keyTag < 0 || $keyTag > 65535) {
|
||||||
|
sendEppError($conn, 2006, 'Invalid keyTag provided', $clTRID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate alg
|
||||||
|
$validAlgorithms = [2, 3, 5, 6, 7, 8, 10, 13, 14, 15, 16];
|
||||||
|
if (!isset($alg) || !in_array($alg, $validAlgorithms)) {
|
||||||
|
sendEppError($conn, 2006, 'Invalid algorithm', $clTRID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate digestType and digest
|
||||||
|
if (!isset($digestType) || !is_int($digestType)) {
|
||||||
|
sendEppError($conn, 2005, 'Invalid digestType', $clTRID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$validDigests = [
|
||||||
|
1 => 40, // SHA-1
|
||||||
|
2 => 64, // SHA-256
|
||||||
|
4 => 96 // SHA-384
|
||||||
|
];
|
||||||
|
if (!isset($validDigests[$digestType])) {
|
||||||
|
sendEppError($conn, 2006, 'Unsupported digestType', $clTRID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!isset($digest) || strlen($digest) != $validDigests[$digestType] || !ctype_xdigit($digest)) {
|
||||||
|
sendEppError($conn, 2006, 'Invalid digest length or format', $clTRID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$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,
|
||||||
'keyTag' => $keyTag,
|
':keyTag' => $keyTag,
|
||||||
'algorithm' => $algorithm,
|
':alg' => $alg,
|
||||||
'digestType' => $digestType,
|
':digestType' => $digestType,
|
||||||
'digest' => $digest
|
':digest' => $digest
|
||||||
]);
|
]);
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
sendEppError($conn, 2400, 'Database error during dsData removal', $clTRID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($secdnsAdds)) {
|
if (isset($secdnsAdds)) {
|
||||||
$secDNSDataSet = $xml->xpath('//secDNS:dsData');
|
foreach ($secdnsAdds as $secdnsAdd) {
|
||||||
|
$secDNSDataSet = $secdnsAdd->xpath('./secDNS:dsData');
|
||||||
if ($secDNSDataSet) {
|
if ($secDNSDataSet) {
|
||||||
foreach ($secDNSDataSet as $secDNSData) {
|
foreach ($secDNSDataSet as $secDNSData) {
|
||||||
// Extract dsData elements
|
// Extract dsData elements
|
||||||
|
@ -1771,8 +1815,39 @@ function processDomainUpdate($conn, $db, $xml, $clid, $database_type, $trans) {
|
||||||
$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
|
||||||
if (!$keyTag || !$alg || !$digestType || !$digest) {
|
// Validate keyTag
|
||||||
sendEppError($conn, 2005, 'Incomplete or invalid dsData provided', $clTRID);
|
if (!isset($keyTag) || !is_int($keyTag)) {
|
||||||
|
sendEppError($conn, 2005, 'Incomplete keyTag provided', $clTRID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ($keyTag < 0 || $keyTag > 65535) {
|
||||||
|
sendEppError($conn, 2006, 'Invalid keyTag provided', $clTRID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate alg
|
||||||
|
$validAlgorithms = [2, 3, 5, 6, 7, 8, 10, 13, 14, 15, 16];
|
||||||
|
if (!isset($alg) || !in_array($alg, $validAlgorithms)) {
|
||||||
|
sendEppError($conn, 2006, 'Invalid algorithm', $clTRID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate digestType and digest
|
||||||
|
if (!isset($digestType) || !is_int($digestType)) {
|
||||||
|
sendEppError($conn, 2005, 'Invalid digestType', $clTRID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$validDigests = [
|
||||||
|
1 => 40, // SHA-1
|
||||||
|
2 => 64, // SHA-256
|
||||||
|
4 => 96 // SHA-384
|
||||||
|
];
|
||||||
|
if (!isset($validDigests[$digestType])) {
|
||||||
|
sendEppError($conn, 2006, 'Unsupported digestType', $clTRID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!isset($digest) || strlen($digest) != $validDigests[$digestType] || !ctype_xdigit($digest)) {
|
||||||
|
sendEppError($conn, 2006, 'Invalid digest length or format', $clTRID);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1789,12 +1864,33 @@ function processDomainUpdate($conn, $db, $xml, $clid, $database_type, $trans) {
|
||||||
$pubKey = (string) $secDNSData->xpath('secDNS:keyData/secDNS:pubKey')[0];
|
$pubKey = (string) $secDNSData->xpath('secDNS:keyData/secDNS:pubKey')[0];
|
||||||
|
|
||||||
// Data sanity checks for keyData
|
// Data sanity checks for keyData
|
||||||
if (!$flags || !$protocol || !$algKeyData || !$pubKey) {
|
// Validate flags
|
||||||
sendEppError($conn, 2005, 'Incomplete or invalid keyData provided', $clTRID);
|
$validFlags = [256, 257];
|
||||||
|
if (isset($flags) && !in_array($flags, $validFlags)) {
|
||||||
|
sendEppError($conn, 2005, 'Invalid flags', $clTRID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate protocol
|
||||||
|
if (isset($protocol) && $protocol != 3) {
|
||||||
|
sendEppError($conn, 2006, 'Invalid protocol', $clTRID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate algKeyData
|
||||||
|
if (isset($algKeyData)) {
|
||||||
|
sendEppError($conn, 2005, 'Invalid algKeyData encoding', $clTRID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate pubKey
|
||||||
|
if (isset($pubKey) && base64_encode(base64_decode($pubKey, true)) !== $pubKey) {
|
||||||
|
sendEppError($conn, 2005, 'Invalid pubKey encoding', $clTRID);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
$stmt = $db->prepare("INSERT INTO `secdns` (`domain_id`, `maxsiglife`, `interface`, `keytag`, `alg`, `digesttype`, `digest`, `flags`, `protocol`, `keydata_alg`, `pubkey`) VALUES (:domain_id, :maxsiglife, :interface, :keytag, :alg, :digesttype, :digest, :flags, :protocol, :keydata_alg, :pubkey)");
|
$stmt = $db->prepare("INSERT INTO `secdns` (`domain_id`, `maxsiglife`, `interface`, `keytag`, `alg`, `digesttype`, `digest`, `flags`, `protocol`, `keydata_alg`, `pubkey`) VALUES (:domain_id, :maxsiglife, :interface, :keytag, :alg, :digesttype, :digest, :flags, :protocol, :keydata_alg, :pubkey)");
|
||||||
|
|
||||||
$stmt->execute([
|
$stmt->execute([
|
||||||
|
@ -1810,18 +1906,41 @@ function processDomainUpdate($conn, $db, $xml, $clid, $database_type, $trans) {
|
||||||
':keydata_alg' => $algKeyData ?? null,
|
':keydata_alg' => $algKeyData ?? null,
|
||||||
':pubkey' => $pubKey ?? null
|
':pubkey' => $pubKey ?? null
|
||||||
]);
|
]);
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$isMySQLUniqueViolation = $e->getCode() === '23000' && strpos($e->getMessage(), '1062 Duplicate entry') !== false;
|
||||||
|
$isPostgreSQLUniqueViolation = $e->getCode() === '23505';
|
||||||
|
if ($isMySQLUniqueViolation || $isPostgreSQLUniqueViolation) {
|
||||||
|
// Do nothing
|
||||||
|
} else {
|
||||||
|
sendEppError($conn, 2400, 'Database error', $clTRID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($secdnsChg !== null) {
|
if (isset($secdnsChg)) {
|
||||||
$maxSigLife = (int)$secdnsChg->maxSigLife;
|
$maxSigLifeElement = $secdnsChg->xpath('secDNS:maxSigLife');
|
||||||
|
|
||||||
|
if ($maxSigLifeElement && isset($maxSigLifeElement[0])) {
|
||||||
|
$maxSigLife = (int)$maxSigLifeElement[0];
|
||||||
|
|
||||||
|
try {
|
||||||
$stmt = $db->prepare("UPDATE secdns SET maxSigLife = :maxSigLife WHERE domain_id = :domain_id");
|
$stmt = $db->prepare("UPDATE secdns SET maxSigLife = :maxSigLife WHERE domain_id = :domain_id");
|
||||||
$stmt->execute([
|
$stmt->execute([
|
||||||
'maxSigLife' => $maxSigLife,
|
':maxSigLife' => $maxSigLife,
|
||||||
'domain_id' => $domain_id
|
':domain_id' => $domain_id
|
||||||
]);
|
]);
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
sendEppError($conn, 2400, 'Database error during maxSigLife update', $clTRID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sendEppError($conn, 2005, 'Invalid or missing maxSigLife', $clTRID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue