From ebc2d74396da5bc6f9031309f709730b125753ba Mon Sep 17 00:00:00 2001 From: Roland Haeder Date: Fri, 21 Feb 2014 21:35:30 +0100 Subject: [PATCH] The final hash must be used as an array key for serial numbers, else some packages will end up with hashes from other packages. Signed-off-by: Roland Haeder --- application/hub/main/class_BaseHubSystem.php | 3 +- .../handler/chunks/class_ChunkHandler.php | 39 ++++++++++++++++--- .../connection/class_BaseConnectionHelper.php | 28 +++++++------ .../fragmenter/class_PackageFragmenter.php | 31 ++++++++------- core | 2 +- 5 files changed, 70 insertions(+), 33 deletions(-) diff --git a/application/hub/main/class_BaseHubSystem.php b/application/hub/main/class_BaseHubSystem.php index a14384e1c..4af449242 100644 --- a/application/hub/main/class_BaseHubSystem.php +++ b/application/hub/main/class_BaseHubSystem.php @@ -31,7 +31,8 @@ class BaseHubSystem extends BaseFrameworkSystem { const EXCEPTION_BASE64_ENCODING_NOT_MODULO_4 = 0x905; const EXCEPTION_NODE_SESSION_ID_NOT_VERIFYING = 0x906; const EXCEPTION_REQUEST_NOT_ACCEPTED = 0x907; - const SOCKET_ERROR_CONNECTION_RESET_BY_PEER = 0x908; + const EXCEPTION_DHT_BOOTSTRAP_NOT_ACCEPTED = 0x908; + const SOCKET_ERROR_CONNECTION_RESET_BY_PEER = 0x909; // Message status codes const MESSAGE_STATUS_CODE_OKAY = 'OKAY'; diff --git a/application/hub/main/handler/chunks/class_ChunkHandler.php b/application/hub/main/handler/chunks/class_ChunkHandler.php index 5b67d1250..5dd182892 100644 --- a/application/hub/main/handler/chunks/class_ChunkHandler.php +++ b/application/hub/main/handler/chunks/class_ChunkHandler.php @@ -285,13 +285,19 @@ class ChunkHandler extends BaseHandler implements HandleableChunks, Registerable * @return void */ private function verifyChunkSerialNumbers () { + // Debug message + //* NOISY-DEBUG */ self::createDebugInstance(__CLASS__)->debugOutput('CHUNK-HANDLER[' . __METHOD__ . ':' . __LINE__ . ']: finalPackageChunks=' . print_r($this->finalPackageChunks, TRUE)); + + // Get final hash + $finalHash = $this->generateFinalHash(implode('', $this->finalPackageChunks['content'])); + // Reset the serial number generator - $this->getFragmenterInstance()->resetSerialNumber(); + $this->getFragmenterInstance()->resetSerialNumber($finalHash); // "Walk" through all (content) chunks foreach ($this->finalPackageChunks['content'] as $serialNumber => $content) { // Get next serial number - $nextSerial = $this->getFragmenterInstance()->getNextHexSerialNumber(); + $nextSerial = $this->getFragmenterInstance()->getNextHexSerialNumber($finalHash); // Debug output //* NOISY-DEBUG */ self::createDebugInstance(__CLASS__)->debugOutput('CHUNK-HANDLER[' . __METHOD__ . ':' . __LINE__ . ']: serialNumber=' . $serialNumber . ',nextSerial=' . $nextSerial); @@ -329,8 +335,8 @@ class ChunkHandler extends BaseHandler implements HandleableChunks, Registerable assert(isset($this->finalPackageChunks['hashes'][$serialNumber])); // Debug message - /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('CHUNK-HANDLER[' . __METHOD__ . ':' . __LINE__ . ']: serialNumber=' . $serialNumber . ',hashes=' . $this->finalPackageChunks['hashes'][$serialNumber] . ' - validating ...'); - /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('finalPackageChunks=' . print_r($this->finalPackageChunks, TRUE) . 'chunkHashes=' . print_r($this->chunkHashes, TRUE)); + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('CHUNK-HANDLER[' . __METHOD__ . ':' . __LINE__ . ']: serialNumber=' . $serialNumber . ',hashes=' . $this->finalPackageChunks['hashes'][$serialNumber] . ' - validating ...'); + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('finalPackageChunks=' . print_r($this->finalPackageChunks, TRUE) . 'chunkHashes=' . print_r($this->chunkHashes, TRUE)); // Is this chunk valid? This should be the case assert($this->isChunkHashValid(array( @@ -353,6 +359,27 @@ class ChunkHandler extends BaseHandler implements HandleableChunks, Registerable assert($this->eopChunk[1] == $this->chunkHashes[count($this->chunkHashes) - 2]); } + /** + * Generate final hash if EOP chunk is found, else an assert will happen. + * + * @param $rawPackageData Raw package data + * @return $finalHash Final hash if EOP chunk is found + */ + private function generateFinalHash ($rawPackageData) { + // Make sure the raw package data is given + assert((is_string($rawPackageData)) && (!empty($rawPackageData))); + + // Make sure the EOP chunk is set + assert((isset($this->eopChunk[0])) && (isset($this->eopChunk[1]))); + assert((is_string($this->eopChunk[0])) && (!empty($this->eopChunk[0]))); + + // Hash the raw data + $finalHash = $this->getCryptoInstance()->hashString($rawPackageData, $this->eopChunk[0], FALSE); + + // Return it + return $finalHash; + } + /** * Verifies the finally assembled raw package data by comparing it against * the final hash. @@ -360,8 +387,8 @@ class ChunkHandler extends BaseHandler implements HandleableChunks, Registerable * @return void */ private function verifyRawPackageData () { - // Hash the raw package data for final verification - $finalHash = $this->getCryptoInstance()->hashString($this->rawPackageData, $this->eopChunk[0], FALSE); + // Generate final hash + $finalHash = $this->generateFinalHash($this->rawPackageData); // Is it the same? //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('CHUNK-HANDLER[' . __METHOD__ . ':' . __LINE__ . ']: eopChunk[1]=' . $this->eopChunk[1] . ',finalHash=' . $finalHash); diff --git a/application/hub/main/helper/connection/class_BaseConnectionHelper.php b/application/hub/main/helper/connection/class_BaseConnectionHelper.php index 8ad8893b0..539198336 100644 --- a/application/hub/main/helper/connection/class_BaseConnectionHelper.php +++ b/application/hub/main/helper/connection/class_BaseConnectionHelper.php @@ -328,22 +328,18 @@ class BaseConnectionHelper extends BaseHubSystemHelper implements Registerable, * @return $chunkData Raw data chunk */ private function getRawDataFromPackageArray (array $packageData) { - // Implode the package data array and fragement the resulting string, returns the final hash - $finalHash = $this->getFragmenterInstance()->fragmentPackageArray($packageData, $this); - if ($finalHash !== TRUE) { - // Debug message - /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('CONNECTION-HELPER[' . __METHOD__ . ':' . __LINE__ . ']: Setting finalHash=' . $finalHash . ',currentFinalHash[' . gettype($this->currentFinalHash) . ']=' . $this->currentFinalHash); - - // Set final hash - $this->currentFinalHash = $finalHash; - } // END - if - // Debug message //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('CONNECTION-HELPER[' . __METHOD__ . ':' . __LINE__ . ']: currentFinalHash=' . $this->currentFinalHash); + // Make sure the final hash is set + assert((is_string($this->currentFinalHash)) && (!empty($this->currentFinalHash))); + // Get the next raw data chunk from the fragmenter $rawDataChunk = $this->getFragmenterInstance()->getNextRawDataChunk($this->currentFinalHash); + // Debug message + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('CONNECTION-HELPER[' . __METHOD__ . ':' . __LINE__ . ']: rawDataChunk=' . print_r($rawDataChunk, TRUE)); + // Get chunk hashes and chunk data $chunkHashes = array_keys($rawDataChunk); $chunkData = array_values($rawDataChunk); @@ -387,8 +383,18 @@ class BaseConnectionHelper extends BaseHubSystemHelper implements Registerable, // The helper's state must be 'connected' $this->getStateInstance()->validatePeerStateConnected(); + // Implode the package data array and fragement the resulting string, returns the final hash + $finalHash = $this->getFragmenterInstance()->fragmentPackageArray($packageData, $this); + if ($finalHash !== TRUE) { + // Debug message + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('CONNECTION-HELPER[' . __METHOD__ . ':' . __LINE__ . ']: Setting finalHash=' . $finalHash . ',currentFinalHash[' . gettype($this->currentFinalHash) . ']=' . $this->currentFinalHash); + + // Set final hash + $this->currentFinalHash = $finalHash; + } // END - if + // Reset serial number - $this->getFragmenterInstance()->resetSerialNumber(); + $this->getFragmenterInstance()->resetSerialNumber($this->currentFinalHash); // Cache buffer length $bufferSize = $this->getConfigInstance()->getConfigEntry($this->getProtocol() . '_buffer_length'); diff --git a/application/hub/main/package/fragmenter/class_PackageFragmenter.php b/application/hub/main/package/fragmenter/class_PackageFragmenter.php index d0fbf3fd0..87641ac93 100644 --- a/application/hub/main/package/fragmenter/class_PackageFragmenter.php +++ b/application/hub/main/package/fragmenter/class_PackageFragmenter.php @@ -57,9 +57,9 @@ class PackageFragmenter extends BaseHubSystem implements Fragmentable, Registera private $processedPackages = array(); /** - * Serial number + * Serial numbers (array key is final hash) */ - private $serialNumber = 0x00000000; + private $serialNumber = array(); /** * Maximum possible serial number, "cache" for speeding up things @@ -361,7 +361,7 @@ class PackageFragmenter extends BaseHubSystem implements Fragmentable, Registera // Prepend the hash to the chunk $rawData = ( $rawDataHash . self::CHUNK_DATA_HASH_SEPARATOR . - $this->getNextHexSerialNumber() . self::CHUNK_DATA_HASH_SEPARATOR . + $this->getNextHexSerialNumber($finalHash) . self::CHUNK_DATA_HASH_SEPARATOR . $chunkData . self::CHUNK_SEPARATOR ); @@ -409,18 +409,19 @@ class PackageFragmenter extends BaseHubSystem implements Fragmentable, Registera /** * "Getter" for the next hexadecimal-encoded serial number * + * @param $finalHash Final hash * @return $encodedSerialNumber The next hexadecimal-encoded serial number */ - public function getNextHexSerialNumber () { + public function getNextHexSerialNumber ($finalHash) { // Assert on maximum serial number length - assert($this->serialNumber <= $this->maxSerialNumber); + assert($this->serialNumber[$finalHash] <= $this->maxSerialNumber); // Encode the current serial number - /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(__METHOD__ . ': serialNumber=' . $this->serialNumber); - $encodedSerialNumber = $this->dec2Hex($this->serialNumber, self::MAX_SERIAL_LENGTH); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(__METHOD__ . ': serialNumber[' . $finalHash . ']=' . $this->serialNumber[$finalHash]); + $encodedSerialNumber = $this->dec2Hex($this->serialNumber[$finalHash], self::MAX_SERIAL_LENGTH); // Count one up - $this->serialNumber++; + $this->serialNumber[$finalHash]++; // Return the encoded serial number /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(__METHOD__ . ': encodedSerialNumber=' . $encodedSerialNumber); @@ -454,8 +455,9 @@ class PackageFragmenter extends BaseHubSystem implements Fragmentable, Registera // Remember it $this->processedPackages[$this->getProcessedPackagesIndex($packageData)] = $finalHash; - // Init pointer + // Init pointer and reset serial number $this->initPointer($finalHash); + $this->resetSerialNumber($finalHash); // Split the encoded data into smaller chunks $this->splitEncodedDataIntoChunks($rawData, $finalHash); @@ -525,16 +527,17 @@ class PackageFragmenter extends BaseHubSystem implements Fragmentable, Registera } /** - * Resets the serial number to zero + * Resets the serial number to zero for given final hash * + * @param $finalHash Final hash to reset counter for * @return void */ - public function resetSerialNumber () { - // Debug message - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('FRAGMENTER: Resetting serial number, previous=' . $this->serialNumber); + public function resetSerialNumber ($finalHash) { + // Final hash must be set + assert((is_string($finalHash)) && (!empty($finalHash))); // Reset serial number - $this->serialNumber = 0; + $this->serialNumber[$finalHash] = 0; } } diff --git a/core b/core index c68ca324e..6807d3268 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit c68ca324e84a3297fb811ae9356f41a82b3c45ab +Subproject commit 6807d3268e4f233bf224155956ef6858925b58b0 -- 2.39.5