From a377c9e51e81d4a88c0fe4b49afed91353718486 Mon Sep 17 00:00:00 2001 From: Sein Coray Date: Mon, 1 Sep 2025 14:43:43 +0200 Subject: [PATCH 1/9] replaced version comparison function with composer/semvar --- Dockerfile | 11 +- ci/HashtopolisTestFramework.class.php | 5 +- composer.json | 3 +- src/inc/Util.class.php | 35 +---- src/inc/api/APICheckClientVersion.class.php | 5 +- src/inc/load.php | 2 + src/inc/utils/AgentBinaryUtils.class.php | 8 +- src/inc/utils/CrackerBinaryUtils.class.php | 5 +- src/install/updates/update.php | 8 +- .../updates/update_v0.14.4_v0.14.5.php | 7 + .../updates/update_v0.14.4_v0.14.x.php | 131 ------------------ .../updates/update_v0.2.0-beta_v0.2.0.php | 3 +- src/install/updates/update_v0.2.x_v0.3.0.php | 3 +- src/install/updates/update_v0.3.1_v0.3.2.php | 3 +- src/install/updates/update_v0.3.2_v0.4.0.php | 3 +- src/install/updates/update_v0.8.0_v0.9.0.php | 3 +- 16 files changed, 50 insertions(+), 185 deletions(-) delete mode 100644 src/install/updates/update_v0.14.4_v0.14.x.php diff --git a/Dockerfile b/Dockerfile index d42b8068d..33da5c9b6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM alpine/git as preprocess +FROM alpine/git AS preprocess COPY .gi[t] /.git @@ -6,7 +6,7 @@ RUN cd / && git rev-parse --short HEAD > /HEAD; exit 0 # BASE image # ----BEGIN---- -FROM php:8-apache as hashtopolis-server-base +FROM php:8-apache AS hashtopolis-server-base # Enable possible build args for injecting user commands ARG CONTAINER_USER_CMD_PRE @@ -96,7 +96,7 @@ ENTRYPOINT [ "docker-entrypoint.sh" ] # DEVELOPMENT Image # ----BEGIN---- -FROM hashtopolis-server-base as hashtopolis-server-dev +FROM hashtopolis-server-base AS hashtopolis-server-dev # Setting up development requirements, install xdebug RUN yes | pecl install xdebug-3.4.0beta1 && docker-php-ext-enable xdebug \ @@ -143,10 +143,13 @@ USER vscode # PRODUCTION Image # ----BEGIN---- -FROM hashtopolis-server-base as hashtopolis-server-prod +FROM hashtopolis-server-base AS hashtopolis-server-prod COPY --chown=www-data:www-data ./src/ $HASHTOPOLIS_DOCUMENT_ROOT +# protect install/update directory +RUN echo "Order deny,allow\nDeny from all" > "${HASHTOPOLIS_DOCUMENT_ROOT}/install/.htaccess" + RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini" \ && touch "/usr/local/etc/php/conf.d/custom.ini" \ && echo "memory_limit = 256m" >> /usr/local/etc/php/conf.d/custom.ini \ diff --git a/ci/HashtopolisTestFramework.class.php b/ci/HashtopolisTestFramework.class.php index 89325ff2d..8f8f9b945 100644 --- a/ci/HashtopolisTestFramework.class.php +++ b/ci/HashtopolisTestFramework.class.php @@ -1,6 +1,7 @@ getMinVersion()) > 0 || $instance->getMinVersion() == 'master')) { + if (!$upgrade && $version != 'master' && (Comparator::lessThan($version, $instance->getMinVersion()) > 0 || $instance->getMinVersion() == 'master')) { echo "Ignoring " . $instance->getTestName() . ": minimum " . $instance->getMinVersion() . " required, but testing $version...\n"; return false; } - if ($instance->getMaxVersion() != 'master' && (Util::versionComparison($version, $instance->getMaxVersion()) < 0 || $version == 'master')) { + if ($instance->getMaxVersion() != 'master' && (Comparator::lessThan($version, $instance->getMaxVersion()) < 0 || $version == 'master')) { echo "Ignoring " . $instance->getTestName() . ": maximum " . $instance->getMaxVersion() . " required, but testing $version...\n"; return false; } diff --git a/composer.json b/composer.json index 71e85fb34..9dbf758cf 100644 --- a/composer.json +++ b/composer.json @@ -28,7 +28,8 @@ "slim/psr7": "^1.5", "slim/slim": "^4.10", "tuupola/slim-basic-auth": "^3.3", - "tuupola/slim-jwt-auth": "^3.6" + "tuupola/slim-jwt-auth": "^3.6", + "composer/semver": "^3.4" }, "require-dev": { "jangregor/phpstan-prophecy": "^1.0.0", diff --git a/src/inc/Util.class.php b/src/inc/Util.class.php index 8168328ee..e307cdc29 100755 --- a/src/inc/Util.class.php +++ b/src/inc/Util.class.php @@ -27,6 +27,7 @@ use DBA\FileDelete; use DBA\Factory; use DBA\Speed; +use Composer\Semver\Comparator; /** * @@ -198,7 +199,7 @@ public static function checkAgentVersion($type, $version, $silent = false) { } $binary = Factory::getAgentBinaryFactory()->filter([Factory::FILTER => $qF], true); if ($binary != null) { - if (Util::versionComparison($binary->getVersion(), $version) == 1) { + if (Comparator::lessThan($binary->getVersion(), $version) == 1) { if (!$silent) { echo "update $type version... "; } @@ -941,35 +942,7 @@ public static function getStaticArray($val, $id) { * @return int */ public static function versionComparisonBinary($binary1, $binary2) { - return Util::versionComparison($binary1->getVersion(), $binary2->getVersion()); - } - - /** - * @param string $version1 - * @param string $version2 - * @return int 1 if version2 is newer, 0 if equal and -1 if version1 is newer - */ - public static function versionComparison($version1, $version2) { - $version1 = explode(".", $version1); - $version2 = explode(".", $version2); - - for ($i = 0; $i < sizeof($version1) && $i < sizeof($version2); $i++) { - $num1 = (int)$version1[$i]; - $num2 = (int)$version2[$i]; - if ($num1 > $num2) { - return -1; - } - else if ($num1 < $num2) { - return 1; - } - } - if (sizeof($version1) > sizeof($version2)) { - return -1; - } - else if (sizeof($version1) < sizeof($version2)) { - return 1; - } - return 0; + return Comparator::lessThan($binary1->getVersion(), $binary2->getVersion()); } /** @@ -984,7 +957,7 @@ public static function updateVersionComparison($versionString1, $versionString2) $version1 = substr($versionString1, 8, strpos($versionString1, "_", 7) - 8); $version2 = substr($versionString2, 8, strpos($versionString2, "_", 7) - 8); - return Util::versionComparison($version2, $version1); + return Comparator::lessThan($version2, $version1); } /** diff --git a/src/inc/api/APICheckClientVersion.class.php b/src/inc/api/APICheckClientVersion.class.php index 64547fd0e..0713fc1db 100644 --- a/src/inc/api/APICheckClientVersion.class.php +++ b/src/inc/api/APICheckClientVersion.class.php @@ -3,6 +3,7 @@ use DBA\AgentBinary; use DBA\QueryFilter; use DBA\Factory; +use Composer\Semver\Comparator; class APICheckClientVersion extends APIBasic { public function execute($QUERY = array()) { @@ -23,7 +24,7 @@ public function execute($QUERY = array()) { } $this->updateAgent(PActions::CHECK_CLIENT_VERSION); - if (Util::versionComparison($result->getVersion(), $version) == -1) { + if (Comparator::lessThan($result->getVersion(), $version) == -1) { DServerLog::log(DServerLog::DEBUG, "Agent " . $this->agent->getId() . " got notified about client update"); $this->sendResponse(array( PResponseClientUpdate::ACTION => PActions::CHECK_CLIENT_VERSION, @@ -42,4 +43,4 @@ public function execute($QUERY = array()) { ); } } -} \ No newline at end of file +} diff --git a/src/inc/load.php b/src/inc/load.php index 70e1a61f2..23e0ceff7 100755 --- a/src/inc/load.php +++ b/src/inc/load.php @@ -12,6 +12,8 @@ session_start(); +require_once(dirname(__FILE__) . "/../../vendor/autoload.php"); + require_once(dirname(__FILE__) . "/info.php"); include(dirname(__FILE__) . "/confv2.php"); diff --git a/src/inc/utils/AgentBinaryUtils.class.php b/src/inc/utils/AgentBinaryUtils.class.php index c7c9d265e..19539aa93 100644 --- a/src/inc/utils/AgentBinaryUtils.class.php +++ b/src/inc/utils/AgentBinaryUtils.class.php @@ -4,8 +4,10 @@ use DBA\QueryFilter; use DBA\User; use DBA\Factory; +use Composer\Semver\Comparator; + +require_once(__DIR__ . "/../apiv2/common/ErrorHandler.class.php"); -require_once __DIR__ . '/../apiv2/common/ErrorHandler.class.php'; class AgentBinaryUtils { /** * @param string $type @@ -226,9 +228,9 @@ public static function getAgentUpdate($agent, $track) { if (strlen($latest) == 0) { throw new HTException("Failed to retrieve latest version!"); } - if (Util::versionComparison($agent->getVersion(), $latest) > 0) { + if (Comparator::lessThan($agent->getVersion(), $latest) > 0) { return $latest; } return false; } -} \ No newline at end of file +} diff --git a/src/inc/utils/CrackerBinaryUtils.class.php b/src/inc/utils/CrackerBinaryUtils.class.php index 5634c565b..5f9818343 100644 --- a/src/inc/utils/CrackerBinaryUtils.class.php +++ b/src/inc/utils/CrackerBinaryUtils.class.php @@ -3,6 +3,7 @@ use DBA\CrackerBinary; use DBA\QueryFilter; use DBA\Factory; +use Composer\Semver\Comparator; class CrackerBinaryUtils { /** @@ -16,7 +17,7 @@ public static function getNewestVersion($crackerBinaryTypeId) { /** @var $newest CrackerBinary */ $newest = null; foreach ($binaries as $binary) { - if ($newest == null || Util::versionComparison($binary->getVersion(), $newest->getVersion()) < 0) { + if ($newest == null || Comparator::lessThan($binary->getVersion(), $newest->getVersion()) < 0) { $newest = $binary; } } @@ -25,4 +26,4 @@ public static function getNewestVersion($crackerBinaryTypeId) { } return $newest; } -} \ No newline at end of file +} diff --git a/src/install/updates/update.php b/src/install/updates/update.php index 59f9bbad0..df99379b1 100644 --- a/src/install/updates/update.php +++ b/src/install/updates/update.php @@ -3,6 +3,7 @@ use DBA\LikeFilterInsensitive; use DBA\StoredValue; use DBA\Factory; +use Composer\Semver\Comparator; /* * This script should automatically determine the current base function and go through @@ -46,10 +47,9 @@ usort($allFiles, array("Util", "updateVersionComparison")); foreach ($allFiles as $file) { if (Util::startsWith($file, "update_v")) { - // check version - $minor = Util::getMinorVersion(substr($file, 8, strpos($file, "_", 7) - 8)); - if (Util::versionComparison($minor, Util::getMinorVersion($storedVersion->getVal())) < 1) { - // script needs to be checked + $startVersion = substr($file, 8, strpos($file, "_", 7) - 8); + if (Comparator::greaterThanOrEqualTo($startVersion, $storedVersion->getVal())) { + // script needs to be executed include(dirname(__FILE__) . "/" . $file); } } diff --git a/src/install/updates/update_v0.14.4_v0.14.5.php b/src/install/updates/update_v0.14.4_v0.14.5.php index ff3347ba9..b3aaac8bd 100644 --- a/src/install/updates/update_v0.14.4_v0.14.5.php +++ b/src/install/updates/update_v0.14.4_v0.14.5.php @@ -10,6 +10,13 @@ $EXECUTED["v0.14.4_agentBinaries"] = true; } +if (!isset($PRESENT["v0.14.4_update_agent_binary"])) { + if (Util::databaseColumnExists("AgentBinary", "type")) { + Factory::getAgentFactory()->getDB()->query("ALTER TABLE `AgentBinary` RENAME COLUMN `type` to `binaryType`;"); + $EXECUTED["v0.14.4_update_agent_binary"] = true; + } +} + if (!isset($PRESENT["v0.14.4_update_hashtypes"])){ $hashTypes = [ new HashType( 1310, "sha224($pass.$salt)", 1, 0), diff --git a/src/install/updates/update_v0.14.4_v0.14.x.php b/src/install/updates/update_v0.14.4_v0.14.x.php deleted file mode 100644 index 46adb0093..000000000 --- a/src/install/updates/update_v0.14.4_v0.14.x.php +++ /dev/null @@ -1,131 +0,0 @@ -getDB()->query("ALTER TABLE `AgentBinary` RENAME COLUMN `type` to `binaryType`;"); - $EXECUTED["v0.14.x_update_agent_binary"] = true; - } -} - -if (!isset($PRESENT["v0.14.x_update_hashtypes"])){ - $hashTypes = [ - new HashType( 1310, "sha224($pass.$salt)", 1, 0), - new HashType( 1320, "sha224($salt.$pass)", 1, 0), - new HashType( 2630, "md5(md5($pass.$salt))", 1, 0), - new HashType( 3610, "md5(md5(md5($pass)).$salt)", 1, 0), - new HashType( 3730, "md5($salt1.strtoupper(md5($salt2.$pass)))", 0, 0), - new HashType( 4420, "md5(sha1($pass.$salt))", 1, 0), - new HashType( 4430, "md5(sha1($salt.$pass))", 1, 0), - new HashType( 5720, "Cisco-ISE Hashed Password (SHA256)", 0, 0), - new HashType( 6050, "HMAC-RIPEMD160 (key = $pass)", 1, 0), - new HashType( 6060, "HMAC-RIPEMD160 (key = $salt)", 1, 0), - new HashType( 7350, "IPMI2 RAKP HMAC-MD5", 0, 0), - new HashType( 8501, "AS/400 DES", 0, 0), - new HashType( 10510, "PDF 1.3 - 1.6 (Acrobat 4 - 8) w/ RC4-40", 0, 1), - new HashType( 12150, "Apache Shiro 1 SHA-512", 0, 1), - new HashType( 14200, "RACF KDFAES", 0, 1), - new HashType( 16501, "Perl Mojolicious session cookie (HMAC-SHA256, >= v9.19)", 0, 0), - new HashType( 17020, "GPG (AES-128/AES-256 (SHA-512($pass)))", 0, 1), - new HashType( 17030, "GPG (AES-128/AES-256 (SHA-256($pass)))", 0, 1), - new HashType( 17040, "GPG (CAST5 (SHA-1($pass)))", 0, 1), - new HashType( 19210, "QNX 7 /etc/shadow (SHA512)", 0, 1), - new HashType( 20712, "RSA Security Analytics / NetWitness (sha256)", 1, 0), - new HashType( 20730, "sha256(sha256($pass.$salt))", 1, 0), - new HashType( 21310, "md5($salt1.sha1($salt2.$pass))", 1, 0), - new HashType( 21900, "md5(md5(md5($pass.$salt1)).$salt2)", 0, 0), - new HashType( 22800, "Simpla CMS - md5($salt.$pass.md5($pass))", 1, 0), - new HashType( 24000, "BestCrypt v4 Volume Encryption", 0, 1), - new HashType( 26610, "MetaMask Wallet (short hash, plaintext check)", 0, 1), - new HashType( 29800, "Bisq .wallet (scrypt)", 0, 1), - new HashType( 29910, "ENCsecurity Datavault (PBKDF2/no keychain)", 0, 1), - new HashType( 29920, "ENCsecurity Datavault (PBKDF2/keychain)", 0, 1), - new HashType( 29930, "ENCsecurity Datavault (MD5/no keychain)", 0, 1), - new HashType( 29940, "ENCsecurity Datavault (MD5/keychain)", 0, 1), - new HashType( 30420, "DANE RFC7929/RFC8162 SHA2-256", 0, 0), - new HashType( 30500, "md5(md5($salt).md5(md5($pass)))", 1, 0), - new HashType( 30600, "bcrypt(sha256($pass))", 0, 1), - new HashType( 30601, "bcrypt(HMAC-SHA256($pass))", 0, 1), - new HashType( 30700, "Anope IRC Services (enc_sha256)", 0, 0), - new HashType( 30901, "Bitcoin raw private key (P2PKH), compressed", 0, 0), - new HashType( 30902, "Bitcoin raw private key (P2PKH), uncompressed", 0, 0), - new HashType( 30903, "Bitcoin raw private key (P2WPKH, Bech32), compressed", 0, 0), - new HashType( 30904, "Bitcoin raw private key (P2WPKH, Bech32), uncompressed", 0, 0), - new HashType( 30905, "Bitcoin raw private key (P2SH(P2WPKH)), compressed", 0, 0), - new HashType( 30906, "Bitcoin raw private key (P2SH(P2WPKH)), uncompressed", 0, 0), - new HashType( 31000, "BLAKE2s-256", 0, 0), - new HashType( 31100, "ShangMi 3 (SM3)", 0, 0), - new HashType( 31200, "Veeam VBK", 0, 1), - new HashType( 31300, "MS SNTP", 0, 0), - new HashType( 31400, "SecureCRT MasterPassphrase v2", 0, 0), - new HashType( 31500, "Domain Cached Credentials (DCC), MS Cache (NT)", 1, 1), - new HashType( 31600, "Domain Cached Credentials 2 (DCC2), MS Cache 2, (NT)", 0, 1), - new HashType( 31700, "md5(md5(md5($pass).$salt1).$salt2)", 1, 0), - new HashType( 31800, "1Password, mobilekeychain (1Password 8)", 0, 1), - new HashType( 31900, "MetaMask Mobile Wallet", 0, 1), - new HashType( 32000, "NetIQ SSPR (MD5)", 0, 1), - new HashType( 32010, "NetIQ SSPR (SHA1)", 0, 1), - new HashType( 32020, "NetIQ SSPR (SHA-1 with Salt)", 0, 1), - new HashType( 32030, "NetIQ SSPR (SHA-256 with Salt)", 0, 1), - new HashType( 32031, "Adobe AEM (SSPR, SHA-256 with Salt)", 0, 1), - new HashType( 32040, "NetIQ SSPR (SHA-512 with Salt)", 0, 1), - new HashType( 32041, "Adobe AEM (SSPR, SHA-512 with Salt)", 0, 1), - new HashType( 32050, "NetIQ SSPR (PBKDF2WithHmacSHA1)", 0, 1), - new HashType( 32060, "NetIQ SSPR (PBKDF2WithHmacSHA256)", 0, 1), - new HashType( 32070, "NetIQ SSPR (PBKDF2WithHmacSHA512)", 0, 1), - new HashType( 32100, "Kerberos 5, etype 17, AS-REP", 0, 1), - new HashType( 32200, "Kerberos 5, etype 18, AS-REP", 0, 1), - new HashType( 32300, "Empire CMS (Admin password)", 1, 0), - new HashType( 32410, "sha512(sha512($pass).$salt)", 1, 0), - new HashType( 32420, "sha512(sha512_bin($pass).$salt)", 1, 0), - new HashType( 32500, "Dogechain.info Wallet", 0, 1), - new HashType( 32600, "CubeCart (whirlpool($salt.$pass.$salt))", 1, 0), - new HashType( 32700, "Kremlin Encrypt 3.0 w/NewDES", 0, 1), - new HashType( 32800, "md5(sha1(md5($pass)))", 0, 0), - new HashType( 32900, "PBKDF1-SHA1", 1, 1), - new HashType( 33000, "md5($salt1.$pass.$salt2)", 1, 0), - new HashType( 33100, "md5($salt.md5($pass).$salt)", 1, 0), - new HashType( 33300, "HMAC-BLAKE2S (key = $pass)", 1, 0), - new HashType( 33400, "mega.nz password-protected link (PBKDF2-HMAC-SHA512)", 0, 1), - new HashType( 33500, "RC4 40-bit DropN", 0, 0), - new HashType( 33501, "RC4 72-bit DropN", 0, 0), - new HashType( 33502, "RC4 104-bit DropN", 0, 0), - new HashType( 33600, "RIPEMD-320", 0, 0), - new HashType( 33650, "HMAC-RIPEMD320 (key = $pass)", 1, 0), - new HashType( 33660, "HMAC-RIPEMD320 (key = $salt)", 1, 0), - new HashType( 33700, "Microsoft Online Account (PBKDF2-HMAC-SHA256 + AES256)", 0, 1), - new HashType( 33800, "WBB4 (Woltlab Burning Board) [bcrypt(bcrypt($pass))]", 0, 1), - new HashType( 33900, "Citrix NetScaler (PBKDF2-HMAC-SHA256)", 0, 1), - new HashType( 34000, "Argon2", 0, 1), - new HashType( 34100, "LUKS v2 argon2 + SHA-256 + AES", 0, 1), - new HashType( 34200, "MurmurHash64A", 1, 0), - new HashType( 34201, "MurmurHash64A (zero seed)", 0, 0), - new HashType( 34211, "MurmurHash64A truncated (zero seed)", 0, 0), - new HashType( 34300, "KeePass (KDBX v4)", 0, 1), - new HashType( 34400, "sha224(sha224($pass))", 0, 0), - new HashType( 34500, "sha224(sha1($pass))", 0, 0), - new HashType( 34600, "MD6 (256)", 0, 0), - new HashType( 34700, "Blockchain, My Wallet, Legacy Wallets", 0, 0), - new HashType( 34800, "BLAKE2b-256", 0, 0), - new HashType( 34810, "BLAKE2b-256($pass.$salt)", 1, 0), - new HashType( 34820, "BLAKE2b-256($salt.$pass)", 1, 0), - new HashType( 35000, "SAP CODVN H (PWDSALTEDHASH) isSHA512", 1, 1), - new HashType( 35100, "sm3crypt $sm3$, SM3 (Unix)", 1, 1), - new HashType( 35200, "AS/400 SSHA1", 1, 0), - new HashType( 70000, "Argon2id [Bridged: reference implementation + tunings]", 0, 1), - new HashType( 70100, "scrypt [Bridged: Scrypt-Jane SMix]", 0, 1), - new HashType( 70200, "scrypt [Bridged: Scrypt-Yescrypt]", 0, 1), - new HashType( 72000, "Generic Hash [Bridged: Python Interpreter free-threading]", 0, 1), - new HashType( 73000, "Generic Hash [Bridged: Python Interpreter with GIL]", 0, 1), - ]; - foreach ($hashTypes as $hashtype) { - $check = Factory::getHashTypeFactory()->get($hashtype->getId()); - if ($check === null) { - Factory::getHashTypeFactory()->save($hashtype); - } - } - $EXECUTED["v0.14.x_update_hashtypes"] = true; -} -?> \ No newline at end of file diff --git a/src/install/updates/update_v0.2.0-beta_v0.2.0.php b/src/install/updates/update_v0.2.0-beta_v0.2.0.php index 5e1fc79a7..9f055dbee 100644 --- a/src/install/updates/update_v0.2.0-beta_v0.2.0.php +++ b/src/install/updates/update_v0.2.0-beta_v0.2.0.php @@ -3,6 +3,7 @@ use DBA\AgentBinary; use DBA\QueryFilter; use DBA\Factory; +use Composer\Semver\Comparator; require_once(dirname(__FILE__) . "/../../inc/load.php"); @@ -20,7 +21,7 @@ $qF = new QueryFilter("type", "csharp", "="); $binary = Factory::getAgentBinaryFactory()->filter([Factory::FILTER => $qF], true); if ($binary != null) { - if (Util::versionComparison($binary->getVersion(), "0.40") == 1) { + if (Comparator::lessThan($binary->getVersion(), "0.40")) { echo "update version... "; $binary->setVersion("0.40"); Factory::getAgentBinaryFactory()->update($binary); diff --git a/src/install/updates/update_v0.2.x_v0.3.0.php b/src/install/updates/update_v0.2.x_v0.3.0.php index 472c858d0..4a2b50a30 100644 --- a/src/install/updates/update_v0.2.x_v0.3.0.php +++ b/src/install/updates/update_v0.2.x_v0.3.0.php @@ -4,6 +4,7 @@ use DBA\Config; use DBA\QueryFilter; use DBA\Factory; +use Composer\Semver\Comparator; require_once(dirname(__FILE__) . "/../../inc/load.php"); @@ -40,7 +41,7 @@ $qF = new QueryFilter("type", "csharp", "="); $binary = Factory::getAgentBinaryFactory()->filter([Factory::FILTER => $qF], true); if ($binary != null) { - if (Util::versionComparison($binary->getVersion(), "0.43") == 1) { + if (Comparator::lessThan($binary->getVersion(), "0.43")) { echo "update version... "; $binary->setVersion("0.43"); Factory::getAgentBinaryFactory()->update($binary); diff --git a/src/install/updates/update_v0.3.1_v0.3.2.php b/src/install/updates/update_v0.3.1_v0.3.2.php index 9a6db7959..438b7a765 100644 --- a/src/install/updates/update_v0.3.1_v0.3.2.php +++ b/src/install/updates/update_v0.3.1_v0.3.2.php @@ -3,6 +3,7 @@ use DBA\AgentBinary; use DBA\QueryFilter; use DBA\Factory; +use Composer\Semver\Comparator; require_once(dirname(__FILE__) . "/../../inc/load.php"); @@ -16,7 +17,7 @@ $qF = new QueryFilter("type", "csharp", "="); $binary = Factory::getAgentBinaryFactory()->filter([Factory::FILTER => $qF], true); if ($binary != null) { - if (Util::versionComparison($binary->getVersion(), "0.43.13") == 1) { + if (Comparator::lessThan($binary->getVersion(), "0.43.13")) { echo "update version... "; $binary->setVersion("0.43.13"); Factory::getAgentBinaryFactory()->update($binary); diff --git a/src/install/updates/update_v0.3.2_v0.4.0.php b/src/install/updates/update_v0.3.2_v0.4.0.php index 5b9330489..bc7c924ee 100644 --- a/src/install/updates/update_v0.3.2_v0.4.0.php +++ b/src/install/updates/update_v0.3.2_v0.4.0.php @@ -3,6 +3,7 @@ use DBA\AgentBinary; use DBA\QueryFilter; use DBA\Factory; +use Composer\Semver\Comparator; require_once(dirname(__FILE__) . "/../../inc/load.php"); @@ -89,7 +90,7 @@ $qF = new QueryFilter("type", "csharp", "="); $binary = Factory::getAgentBinaryFactory()->filter([Factory::FILTER => $qF], true); if ($binary != null) { - if (Util::versionComparison($binary->getVersion(), "0.46.2") == 1) { + if (Comparator::lessThan($binary->getVersion(), "0.46.2")) { echo "update version... "; $binary->setVersion("0.46.2"); Factory::getAgentBinaryFactory()->update($binary); diff --git a/src/install/updates/update_v0.8.0_v0.9.0.php b/src/install/updates/update_v0.8.0_v0.9.0.php index fbdb8d11b..2ad73117e 100644 --- a/src/install/updates/update_v0.8.0_v0.9.0.php +++ b/src/install/updates/update_v0.8.0_v0.9.0.php @@ -6,6 +6,7 @@ use DBA\QueryFilter; use DBA\HashType; use DBA\AgentBinary; +use Composer\Semver\Comparator; if (!isset($TEST)) { /** @noinspection PhpIncludeInspection */ @@ -31,7 +32,7 @@ $qF = new QueryFilter("type", "python", "="); $binary = Factory::getAgentBinaryFactory()->filter([Factory::FILTER => $qF], true); if ($binary != null) { - if (Util::versionComparison($binary->getVersion(), "0.3.0") == 1) { + if (Comparator::lessThan($binary->getVersion(), "0.3.0")) { echo "update python version... "; $binary->setVersion("0.3.0"); Factory::getAgentBinaryFactory()->update($binary); From 6711cc34cffbc3ca1c34121c347c49bb402990dd Mon Sep 17 00:00:00 2001 From: Sein Coray Date: Mon, 1 Sep 2025 15:03:12 +0200 Subject: [PATCH 2/9] fixed comparisons --- ci/HashtopolisTestFramework.class.php | 4 ++-- doc/changelog.md | 5 +++++ src/inc/Util.class.php | 18 +++++++++++++++--- src/inc/api/APICheckClientVersion.class.php | 2 +- src/inc/utils/AgentBinaryUtils.class.php | 2 +- src/inc/utils/CrackerBinaryUtils.class.php | 2 +- 6 files changed, 25 insertions(+), 8 deletions(-) diff --git a/ci/HashtopolisTestFramework.class.php b/ci/HashtopolisTestFramework.class.php index 8f8f9b945..f2a975784 100644 --- a/ci/HashtopolisTestFramework.class.php +++ b/ci/HashtopolisTestFramework.class.php @@ -105,11 +105,11 @@ private function isTestIncluded($instance, $version, $testNames, $runType, $upgr if (!empty($testNames) && !in_array(get_class($instance), $testNames)) { return false; } - if (!$upgrade && $version != 'master' && (Comparator::lessThan($version, $instance->getMinVersion()) > 0 || $instance->getMinVersion() == 'master')) { + if (!$upgrade && $version != 'master' && (Comparator::lessThan($version, $instance->getMinVersion()) || $instance->getMinVersion() == 'master')) { echo "Ignoring " . $instance->getTestName() . ": minimum " . $instance->getMinVersion() . " required, but testing $version...\n"; return false; } - if ($instance->getMaxVersion() != 'master' && (Comparator::lessThan($version, $instance->getMaxVersion()) < 0 || $version == 'master')) { + if ($instance->getMaxVersion() != 'master' && (Comparator::greaterThan($version, $instance->getMaxVersion()) || $version == 'master')) { echo "Ignoring " . $instance->getTestName() . ": maximum " . $instance->getMaxVersion() . " required, but testing $version...\n"; return false; } diff --git a/doc/changelog.md b/doc/changelog.md index 0a12c97ea..70187f233 100644 --- a/doc/changelog.md +++ b/doc/changelog.md @@ -5,6 +5,11 @@ **Enhancements** - Updated OpenAPI docs to latest API updates +- Improved version comparison to avoid update script issues + +**Bugfixes** + +- Fixed missing .htaccess to avoid access to install directory on docker setups ## v0.14.4 -> v0.14.5 diff --git a/src/inc/Util.class.php b/src/inc/Util.class.php index e307cdc29..b3d8eb34a 100755 --- a/src/inc/Util.class.php +++ b/src/inc/Util.class.php @@ -199,7 +199,7 @@ public static function checkAgentVersion($type, $version, $silent = false) { } $binary = Factory::getAgentBinaryFactory()->filter([Factory::FILTER => $qF], true); if ($binary != null) { - if (Comparator::lessThan($binary->getVersion(), $version) == 1) { + if (Comparator::lessThan($binary->getVersion(), $version)) { if (!$silent) { echo "update $type version... "; } @@ -942,7 +942,13 @@ public static function getStaticArray($val, $id) { * @return int */ public static function versionComparisonBinary($binary1, $binary2) { - return Comparator::lessThan($binary1->getVersion(), $binary2->getVersion()); + if (Comparator::greaterThan($binary1->getVersion(), $binary2->getVersion()){ + return 1; + } + else if (Comparator::lessThan($binary1->getVersion(), $binary2->getVersion()){ + return -1; + } + return 0; } /** @@ -957,7 +963,13 @@ public static function updateVersionComparison($versionString1, $versionString2) $version1 = substr($versionString1, 8, strpos($versionString1, "_", 7) - 8); $version2 = substr($versionString2, 8, strpos($versionString2, "_", 7) - 8); - return Comparator::lessThan($version2, $version1); + if(Comparator::greaterThan($version2, $version1)){ + return 1; + } + else if(Comparator::lessThan($version2, $version1)){ + return -1; + } + return 0; } /** diff --git a/src/inc/api/APICheckClientVersion.class.php b/src/inc/api/APICheckClientVersion.class.php index 0713fc1db..53d699b31 100644 --- a/src/inc/api/APICheckClientVersion.class.php +++ b/src/inc/api/APICheckClientVersion.class.php @@ -24,7 +24,7 @@ public function execute($QUERY = array()) { } $this->updateAgent(PActions::CHECK_CLIENT_VERSION); - if (Comparator::lessThan($result->getVersion(), $version) == -1) { + if (Comparator::lessThan($result->getVersion(), $version)) { DServerLog::log(DServerLog::DEBUG, "Agent " . $this->agent->getId() . " got notified about client update"); $this->sendResponse(array( PResponseClientUpdate::ACTION => PActions::CHECK_CLIENT_VERSION, diff --git a/src/inc/utils/AgentBinaryUtils.class.php b/src/inc/utils/AgentBinaryUtils.class.php index 19539aa93..d9325c9ad 100644 --- a/src/inc/utils/AgentBinaryUtils.class.php +++ b/src/inc/utils/AgentBinaryUtils.class.php @@ -228,7 +228,7 @@ public static function getAgentUpdate($agent, $track) { if (strlen($latest) == 0) { throw new HTException("Failed to retrieve latest version!"); } - if (Comparator::lessThan($agent->getVersion(), $latest) > 0) { + if (Comparator::lessThan($agent->getVersion(), $latest)) { return $latest; } return false; diff --git a/src/inc/utils/CrackerBinaryUtils.class.php b/src/inc/utils/CrackerBinaryUtils.class.php index 5f9818343..97a4da603 100644 --- a/src/inc/utils/CrackerBinaryUtils.class.php +++ b/src/inc/utils/CrackerBinaryUtils.class.php @@ -17,7 +17,7 @@ public static function getNewestVersion($crackerBinaryTypeId) { /** @var $newest CrackerBinary */ $newest = null; foreach ($binaries as $binary) { - if ($newest == null || Comparator::lessThan($binary->getVersion(), $newest->getVersion()) < 0) { + if ($newest == null || Comparator::greaterThan($binary->getVersion(), $newest->getVersion())) { $newest = $binary; } } From 30eb46c36b58878abab1af95b225fdc0202d4130 Mon Sep 17 00:00:00 2001 From: Sein Coray Date: Mon, 1 Sep 2025 15:07:25 +0200 Subject: [PATCH 3/9] fixed bracket issue --- src/inc/Util.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/inc/Util.class.php b/src/inc/Util.class.php index b3d8eb34a..2d9982352 100755 --- a/src/inc/Util.class.php +++ b/src/inc/Util.class.php @@ -942,10 +942,10 @@ public static function getStaticArray($val, $id) { * @return int */ public static function versionComparisonBinary($binary1, $binary2) { - if (Comparator::greaterThan($binary1->getVersion(), $binary2->getVersion()){ + if (Comparator::greaterThan($binary1->getVersion(), $binary2->getVersion())){ return 1; } - else if (Comparator::lessThan($binary1->getVersion(), $binary2->getVersion()){ + else if (Comparator::lessThan($binary1->getVersion(), $binary2->getVersion())){ return -1; } return 0; From 65a2de73bd64c7e588cddbc006d22d7ed43b7c82 Mon Sep 17 00:00:00 2001 From: Sein Coray Date: Mon, 1 Sep 2025 15:30:50 +0200 Subject: [PATCH 4/9] we now have to run composer before we can use anything (this would've happened later anyway) --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 512630ccf..37f89b105 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,14 +16,14 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v3 + - name: Install composer dependencies packages + run: docker exec hashtopolis-server-dev composer install --working-dir=/var/www/html/ - name: Start Hashtopolis server uses: ./.github/actions/start-hashtopolis - name: Give Apache permissions on necessary directories # for the tests, only src/files and src/inc/utils/locks seem necessary run: docker exec -u root hashtopolis-server-dev bash -c "chown -R www-data:www-data /var/www/html/src && chmod -R g+w /var/www/html/src" - name: Run test suite run: docker exec hashtopolis-server-dev php /var/www/html/ci/run.php -vmaster - - name: Install composer dependencies packages - run: docker exec hashtopolis-server-dev composer install --working-dir=/var/www/html/ - name: Test with pytest run: docker exec hashtopolis-server-dev pytest /var/www/html/ci/apiv2 - name: Test if pytest is removing all test objects @@ -33,4 +33,4 @@ jobs: run: docker logs hashtopolis-server-dev - name: Show installed files tree in /var/www/html if: ${{ always() }} - run: docker exec hashtopolis-server-dev find /var/www/html \ No newline at end of file + run: docker exec hashtopolis-server-dev find /var/www/html From e605c06cd0334bf9c3d4e80d5690dda5921875ce Mon Sep 17 00:00:00 2001 From: Sein Coray Date: Mon, 1 Sep 2025 15:37:21 +0200 Subject: [PATCH 5/9] moving the composer install (which is needed as it's overwritten by the devcontainer docker-compose file) to before checking for connection --- .github/actions/start-hashtopolis/action.yml | 4 +++- .github/workflows/ci.yml | 2 -- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/actions/start-hashtopolis/action.yml b/.github/actions/start-hashtopolis/action.yml index b5faa2209..1d7a2b9b1 100644 --- a/.github/actions/start-hashtopolis/action.yml +++ b/.github/actions/start-hashtopolis/action.yml @@ -8,6 +8,8 @@ runs: working-directory: .devcontainer run: docker compose up -d shell: bash + - name: Install composer dependencies packages + run: docker exec hashtopolis-server-dev composer install --working-dir=/var/www/html/ - name: Wait until entrypoint is finished and Hashtopolis is started run: bash .github/scripts/await-hashtopolis-startup.sh - shell: bash \ No newline at end of file + shell: bash diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 37f89b105..cc14f4d88 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,8 +16,6 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v3 - - name: Install composer dependencies packages - run: docker exec hashtopolis-server-dev composer install --working-dir=/var/www/html/ - name: Start Hashtopolis server uses: ./.github/actions/start-hashtopolis - name: Give Apache permissions on necessary directories # for the tests, only src/files and src/inc/utils/locks seem necessary From aee754ca8f4eab399f1ac4ded5a94915a0ef7bdf Mon Sep 17 00:00:00 2001 From: Sein Coray Date: Mon, 1 Sep 2025 15:38:15 +0200 Subject: [PATCH 6/9] added missing shell --- .github/actions/start-hashtopolis/action.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/actions/start-hashtopolis/action.yml b/.github/actions/start-hashtopolis/action.yml index 1d7a2b9b1..95d982955 100644 --- a/.github/actions/start-hashtopolis/action.yml +++ b/.github/actions/start-hashtopolis/action.yml @@ -10,6 +10,7 @@ runs: shell: bash - name: Install composer dependencies packages run: docker exec hashtopolis-server-dev composer install --working-dir=/var/www/html/ + shell: bash - name: Wait until entrypoint is finished and Hashtopolis is started run: bash .github/scripts/await-hashtopolis-startup.sh shell: bash From 31ac564621d78a109925c7326cc486d854741d26 Mon Sep 17 00:00:00 2001 From: Sein Coray Date: Mon, 1 Sep 2025 15:45:40 +0200 Subject: [PATCH 7/9] updated composer.lock --- composer.lock | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 78 insertions(+), 1 deletion(-) diff --git a/composer.lock b/composer.lock index 18b6e0c14..5a6444b93 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,85 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "448d813b74a8b1d0a517cf71e22a34a6", + "content-hash": "4e2c70025b277832ee47cab84d7a2ad9", "packages": [ + { + "name": "composer/semver", + "version": "3.4.4", + "source": { + "type": "git", + "url": "https://github.com/composer/semver.git", + "reference": "198166618906cb2de69b95d7d47e5fa8aa1b2b95" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/semver/zipball/198166618906cb2de69b95d7d47e5fa8aa1b2b95", + "reference": "198166618906cb2de69b95d7d47e5fa8aa1b2b95", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.11", + "symfony/phpunit-bridge": "^3 || ^7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Semver\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl" + } + ], + "description": "Semver library that offers utilities, version constraint parsing and validation.", + "keywords": [ + "semantic", + "semver", + "validation", + "versioning" + ], + "support": { + "irc": "ircs://irc.libera.chat:6697/composer", + "issues": "https://github.com/composer/semver/issues", + "source": "https://github.com/composer/semver/tree/3.4.4" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + } + ], + "time": "2025-08-20T19:15:30+00:00" + }, { "name": "crell/api-problem", "version": "3.7.0", From 18e9e2c3af440d2344d240f511ce00c3e8fb6cc7 Mon Sep 17 00:00:00 2001 From: Sein Coray Date: Mon, 1 Sep 2025 16:29:53 +0200 Subject: [PATCH 8/9] just copy over the openapi.json file, no markdown conversion --- .github/workflows/docs-build.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/docs-build.yml b/.github/workflows/docs-build.yml index 3c384247c..da16380cd 100644 --- a/.github/workflows/docs-build.yml +++ b/.github/workflows/docs-build.yml @@ -27,14 +27,13 @@ jobs: sudo apt-get install -y lftp sudo apt-get install nodejs sudo apt-get install npm - sudo npm i openapi-to-md -g - name: Start Hashtopolis server uses: ./.github/actions/start-hashtopolis - name: Download newest apiv2 spec run: | wget http://localhost:8080/api/v2/openapi.json -P /tmp/ cat /tmp/openapi.json - openapi-to-md /tmp/openapi.json ./doc/api/ + mv /tmp/openapi.json ./doc/ - name: Create function level documentation with phpdocumentor run: | wget https://phpdoc.org/phpDocumentor.phar -P /tmp/ From 2569e021f169c5d631552ad97a10034ad5be3e52 Mon Sep 17 00:00:00 2001 From: Sein Coray Date: Mon, 1 Sep 2025 16:37:16 +0200 Subject: [PATCH 9/9] also fix openapi.json on docs.yml --- .github/workflows/docs.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 8a00bf9e5..c48bf4ddc 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -27,14 +27,13 @@ jobs: sudo apt-get install -y lftp sudo apt-get install nodejs sudo apt-get install npm - sudo npm i openapi-to-md -g - name: Start Hashtopolis server uses: ./.github/actions/start-hashtopolis - name: Download newest apiv2 spec run: | wget http://localhost:8080/api/v2/openapi.json -P /tmp/ cat /tmp/openapi.json - openapi-to-md /tmp/openapi.json ./doc/api/ + mv /tmp/openapi.json ./doc/ - name: Create function level documentation with phpdocumentor run: | wget https://phpdoc.org/phpDocumentor.phar -P /tmp/