From 57edb4a38554cd82de79c81e8605120be653c541 Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Fri, 28 Mar 2025 08:17:47 +0100 Subject: [PATCH] Removed leftovers --- README.md | 2 +- app/terminal.php | 194 --------------- src/Appwrite/Auth/Hash/Argon2.php | 47 ---- src/Appwrite/Auth/Hash/Bcrypt.php | 46 ---- src/Appwrite/Auth/Hash/Md5.php | 44 ---- src/Appwrite/Auth/Hash/Phpass.php | 290 ---------------------- src/Appwrite/Auth/Hash/Scrypt.php | 51 ---- src/Appwrite/Auth/Hash/Scryptmodified.php | 80 ------ src/Appwrite/Auth/Hash/Sha.php | 50 ---- 9 files changed, 1 insertion(+), 803 deletions(-) delete mode 100644 app/terminal.php delete mode 100644 src/Appwrite/Auth/Hash/Argon2.php delete mode 100644 src/Appwrite/Auth/Hash/Bcrypt.php delete mode 100644 src/Appwrite/Auth/Hash/Md5.php delete mode 100644 src/Appwrite/Auth/Hash/Phpass.php delete mode 100644 src/Appwrite/Auth/Hash/Scrypt.php delete mode 100644 src/Appwrite/Auth/Hash/Scryptmodified.php delete mode 100644 src/Appwrite/Auth/Hash/Sha.php diff --git a/README.md b/README.md index 4af1370403..c3585dbb68 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -> [Get started with Appwrite](https://apwr.dev/appcloud) +> [Get started with Appwrite](https://apwr.dev/appcloud)

diff --git a/app/terminal.php b/app/terminal.php deleted file mode 100644 index 1d2f2f0b24..0000000000 --- a/app/terminal.php +++ /dev/null @@ -1,194 +0,0 @@ -column('userId', Table::TYPE_STRING, 64); -$runtimes->column('runtimeHost', Table::TYPE_STRING, 255); -$runtimes->column('runtimePort', Table::TYPE_INT); -$runtimes->create(); - -// Store WebSocket client connections -$clients = []; - -const MAX_PACKAGE_LENGTH = 64000; -const MAX_RUNTIME_CONNECTIONS = 4096; - -$adapter = new Adapter\Swoole(port: System::getEnv('PORT', 80)); -$adapter - ->setPackageMaxLength(MAX_PACKAGE_LENGTH) - ->setWorkerNumber($workerNumber); - -$server = new Server($adapter); - -$server->onStart(function () use ($workerNumber) { - Console::success('Terminal WebSocket Proxy started successfully'); - Console::info('Listening on port: ' . System::getEnv('PORT', 80)); - Console::info('Worker processes: ' . $workerNumber); - Console::info('Max package length: ' . (MAX_PACKAGE_LENGTH / 1000) . 'KB'); - Console::info('Max runtime connections: ' . MAX_RUNTIME_CONNECTIONS); -}); - -$server->onOpen(function (int $connection, $request) use ($server, $runtimes, &$clients) { - try { - Console::info("New connection: {$connection}"); - - // Extract JWT from request - $token = $request->header['authorization'] ?? ''; - if (empty($token)) { - throw new Exception('Missing authentication token', 401); - } - - // Verify JWT and extract user information - $jwt = str_replace('Bearer ', '', $token); - $key = System::getEnv('_APP_OPENSSL_KEY_V1', ''); - $jwt = new JWT($key, 'HS256', 900, 0); - - try { - $payload = $jwt->decode($token); - $userId = $payload['userId'] ?? ''; - $sessionId = $payload['sessionId'] ?? ''; - - if (empty($userId) || empty($sessionId)) { - throw new Exception('Invalid JWT payload', 401); - } - } catch (\Exception $e) { - throw new Exception('Invalid JWT token', 401); - } - - // Get runtime details for user (this could come from your database/cache) - $runtimeHost = "runtime-{$userId}.internal"; // Example hostname - $runtimePort = 9000; - - // Create WebSocket connection to runtime - go(function () use ($server, $connection, &$clients, $runtimeHost, $runtimePort, $userId) { - try { - // $wsClient = new Client("ws://{$runtimeHost}:{$runtimePort}/", [ - // 'timeout' => 0, // Disable timeout for long-running connections - // 'filter' => ['text', 'binary', 'close'] // Only process these frame types - // ]); - - - $wsClient = new Client( - "ws://appwrite-traefik/v1/realtime", - [ - "headers" => [], - "timeout" => 30, - ] - ); - - // Store client connection - $clients[$connection] = [ - 'client' => $wsClient, - 'userId' => $userId - ]; - - // Forward messages from runtime back to client - while (true) { - try { - $message = $wsClient->receive(); - if ($message === null) { - // Connection closed normally - break; - } - $server->send([$connection], $message); - - // Yield to allow other coroutines to run - Swoole\Coroutine::yield(); - - } catch (\WebSocket\ConnectionException $e) { - Console::error("Runtime connection error for user {$userId}: " . $e->getMessage()); - break; - } - } - - // Cleanup on disconnect - $wsClient->close(); - unset($clients[$connection]); - $server->close($connection, CLOSE_NORMAL); - } catch (\WebSocket\ConnectionException $e) { - Console::error("Failed to connect to runtime for user {$userId}: " . $e->getMessage()); - $server->close($connection, CLOSE_SERVER_ERROR); - return; - } - }); - - // Send successful connection message - $server->send([$connection], json_encode([ - 'type' => 'connected', - 'data' => [ - 'userId' => $userId, - 'timestamp' => time() - ] - ])); - - } catch (Throwable $th) { - Console::error('Connection error: ' . $th->getMessage()); - - $server->send([$connection], json_encode([ - 'type' => 'error', - 'data' => [ - 'code' => $th->getCode(), - 'message' => $th->getMessage() - ] - ])); - - $server->close($connection, CLOSE_POLICY_VIOLATION); - } -}); - -$server->onMessage(function (int $connection, string $message) use ($server, &$clients) { - try { - if (!isset($clients[$connection])) { - throw new Exception('Client not connected to runtime', 1008); - } - - $wsClient = $clients[$connection]['client']; - try { - // Forward message to runtime - $wsClient->send($message); - } catch (\WebSocket\ConnectionException $e) { - throw new Exception('Runtime connection lost: ' . $e->getMessage(), 1008); - } - - } catch (Throwable $th) { - $server->send([$connection], json_encode([ - 'type' => 'error', - 'data' => [ - 'code' => $th->getCode(), - 'message' => $th->getMessage() - ] - ])); - - if ($th->getCode() === 1008) { - $server->close($connection, CLOSE_POLICY_VIOLATION); - } - } -}); - -$server->onClose(function (int $connection) use (&$clients) { - if (isset($clients[$connection])) { - $userId = $clients[$connection]['userId']; - $clients[$connection]['client']->close(); - unset($clients[$connection]); - Console::info("Closed connection for user {$userId}"); - } -}); - -$server->start(); \ No newline at end of file diff --git a/src/Appwrite/Auth/Hash/Argon2.php b/src/Appwrite/Auth/Hash/Argon2.php deleted file mode 100644 index c723b077b1..0000000000 --- a/src/Appwrite/Auth/Hash/Argon2.php +++ /dev/null @@ -1,47 +0,0 @@ -getOptions()); - } - - /** - * @param string $password Input password to validate - * @param string $hash Hash to verify password against - * - * @return boolean true if password matches hash - */ - public function verify(string $password, string $hash): bool - { - return \password_verify($password, $hash); - } - - /** - * Get default options for specific hashing algo - * - * @return array options named array - */ - public function getDefaultOptions(): array - { - return ['memory_cost' => 65536, 'time_cost' => 4, 'threads' => 3]; - } -} diff --git a/src/Appwrite/Auth/Hash/Bcrypt.php b/src/Appwrite/Auth/Hash/Bcrypt.php deleted file mode 100644 index 8b6177f33a..0000000000 --- a/src/Appwrite/Auth/Hash/Bcrypt.php +++ /dev/null @@ -1,46 +0,0 @@ -getOptions()); - } - - /** - * @param string $password Input password to validate - * @param string $hash Hash to verify password against - * - * @return boolean true if password matches hash - */ - public function verify(string $password, string $hash): bool - { - return \password_verify($password, $hash); - } - - /** - * Get default options for specific hashing algo - * - * @return array options named array - */ - public function getDefaultOptions(): array - { - return [ 'cost' => 8 ]; - } -} diff --git a/src/Appwrite/Auth/Hash/Md5.php b/src/Appwrite/Auth/Hash/Md5.php deleted file mode 100644 index 8ade3dd5e2..0000000000 --- a/src/Appwrite/Auth/Hash/Md5.php +++ /dev/null @@ -1,44 +0,0 @@ -hash($password) === $hash; - } - - /** - * Get default options for specific hashing algo - * - * @return array options named array - */ - public function getDefaultOptions(): array - { - return []; - } -} diff --git a/src/Appwrite/Auth/Hash/Phpass.php b/src/Appwrite/Auth/Hash/Phpass.php deleted file mode 100644 index 988c38cc8d..0000000000 --- a/src/Appwrite/Auth/Hash/Phpass.php +++ /dev/null @@ -1,290 +0,0 @@ - in 2004-2017 and placed in - * the public domain. Revised in subsequent years, still public domain. - * There's absolutely no warranty. - * The homepage URL for the source framework is: http://www.openwall.com/phpass/ - * Please be sure to update the Version line if you edit this file in any way. - * It is suggested that you leave the main version number intact, but indicate - * your project name (after the slash) and add your own revision information. - * Please do not change the "private" password hashing method implemented in - * here, thereby making your hashes incompatible. However, if you must, please - * change the hash type identifier (the "$P$") to something different. - * Obviously, since this code is in the public domain, the above are not - * requirements (there can be none), but merely suggestions. - * - * @author Solar Designer - * @copyright Copyright (C) 2017 All rights reserved. - * @license http://www.opensource.org/licenses/mit-license.html MIT License; see LICENSE.txt - */ - -namespace Appwrite\Auth\Hash; - -use Appwrite\Auth\Hash; - -/* - * PHPass accepted options: - * int iteration_count_log2; The Logarithmic cost value used when generating hash values indicating the number of rounds used to generate hashes - * string portable_hashes - * string random_state; The cached random state - * - * Reference: https://github.com/photodude/phpass -*/ -class Phpass extends Hash -{ - /** - * Alphabet used in itoa64 conversions. - * - * @var string - * @since 0.1.0 - */ - protected string $itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; - - /** - * Get default options for specific hashing algo - * - * @return array options named array - */ - public function getDefaultOptions(): array - { - $randomState = \microtime(); - if (\function_exists('getmypid')) { - $randomState .= getmypid(); - } - - return ['iteration_count_log2' => 8, 'portable_hashes' => false, 'random_state' => $randomState]; - } - - /** - * @param string $password Input password to hash - * - * @return string hash - */ - public function hash(string $password): string - { - $options = $this->getDefaultOptions(); - - $random = ''; - if (CRYPT_BLOWFISH === 1 && !$options['portable_hashes']) { - $random = $this->getRandomBytes(16, $options); - $hash = crypt($password, $this->gensaltBlowfish($random, $options)); - if (strlen($hash) === 60) { - return $hash; - } - } - if (strlen($random) < 6) { - $random = $this->getRandomBytes(6, $options); - } - $hash = $this->cryptPrivate($password, $this->gensaltPrivate($random, $options)); - if (strlen($hash) === 34) { - return $hash; - } - - /** - * Returning '*' on error is safe here, but would _not_ be safe - * in a crypt(3)-like function used _both_ for generating new - * hashes and for validating passwords against existing hashes. - */ - return '*'; - } - - /** - * @param string $password Input password to validate - * @param string $hash Hash to verify password against - * - * @return boolean true if password matches hash - */ - public function verify(string $password, string $hash): bool - { - $verificationHash = $this->cryptPrivate($password, $hash); - if ($verificationHash[0] === '*') { - $verificationHash = crypt($password, $hash); - } - - /** - * This is not constant-time. In order to keep the code simple, - * for timing safety we currently rely on the salts being - * unpredictable, which they are at least in the non-fallback - * cases (that is, when we use /dev/urandom and bcrypt). - */ - return $hash === $verificationHash; - } - - /** - * @param int $count - * - * @return String $output - * @since 0.1.0 - * @throws Exception Thows an Exception if the $count parameter is not a positive integer. - */ - protected function getRandomBytes(int $count, array $options): string - { - if (!is_int($count) || $count < 1) { - throw new \Exception('Argument count must be a positive integer'); - } - $output = ''; - if (@is_readable('/dev/urandom') && ($fh = @fopen('/dev/urandom', 'rb'))) { - $output = fread($fh, $count); - fclose($fh); - } - - if (strlen($output) < $count) { - $output = ''; - - for ($i = 0; $i < $count; $i += 16) { - $options['iteration_count_log2'] = md5(microtime() . $options['iteration_count_log2']); - $output .= md5($options['iteration_count_log2'], true); - } - - $output = substr($output, 0, $count); - } - - return $output; - } - - /** - * @param String $input - * @param int $count - * - * @return String $output - * @since 0.1.0 - * @throws Exception Thows an Exception if the $count parameter is not a positive integer. - */ - protected function encode64($input, $count) - { - if (!is_int($count) || $count < 1) { - throw new \Exception('Argument count must be a positive integer'); - } - $output = ''; - $i = 0; - do { - $value = ord($input[$i++]); - $output .= $this->itoa64[$value & 0x3f]; - if ($i < $count) { - $value |= ord($input[$i]) << 8; - } - $output .= $this->itoa64[($value >> 6) & 0x3f]; - if ($i++ >= $count) { - break; - } - if ($i < $count) { - $value |= ord($input[$i]) << 16; - } - $output .= $this->itoa64[($value >> 12) & 0x3f]; - if ($i++ >= $count) { - break; - } - $output .= $this->itoa64[($value >> 18) & 0x3f]; - } while ($i < $count); - - return $output; - } - - /** - * @param String $input - * - * @return String $output - * @since 0.1.0 - */ - private function gensaltPrivate($input, $options) - { - $output = '$P$'; - $output .= $this->itoa64[min($options['iteration_count_log2'] + ((PHP_VERSION >= '5') ? 5 : 3), 30)]; - $output .= $this->encode64($input, 6); - - return $output; - } - - /** - * @param String $password - * @param String $setting - * - * @return String $output - * @since 0.1.0 - */ - private function cryptPrivate($password, $setting) - { - $output = '*0'; - if (substr($setting, 0, 2) === $output) { - $output = '*1'; - } - $id = substr($setting, 0, 3); - // We use "$P$", phpBB3 uses "$H$" for the same thing - if ($id !== '$P$' && $id !== '$H$') { - return $output; - } - $count_log2 = strpos($this->itoa64, $setting[3]); - if ($count_log2 < 7 || $count_log2 > 30) { - return $output; - } - $count = 1 << $count_log2; - $salt = substr($setting, 4, 8); - if (strlen($salt) !== 8) { - return $output; - } - /** - * We were kind of forced to use MD5 here since it's the only - * cryptographic primitive that was available in all versions of PHP - * in use. To implement our own low-level crypto in PHP - * would have result in much worse performance and - * consequently in lower iteration counts and hashes that are - * quicker to crack (by non-PHP code). - */ - $hash = md5($salt . $password, true); - do { - $hash = md5($hash . $password, true); - } while (--$count); - $output = substr($setting, 0, 12); - $output .= $this->encode64($hash, 16); - - return $output; - } - - /** - * @param String $input - * - * @return String $output - * @since 0.1.0 - */ - private function gensaltBlowfish($input, $options) - { - /** - * This one needs to use a different order of characters and a - * different encoding scheme from the one in encode64() above. - * We care because the last character in our encoded string will - * only represent 2 bits. While two known implementations of - * bcrypt will happily accept and correct a salt string which - * has the 4 unused bits set to non-zero, we do not want to take - * chances and we also do not want to waste an additional byte - * of entropy. - */ - $itoa64 = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; - $output = '$2a$'; - $output .= chr(ord('0') + intval($options['iteration_count_log2'] / 10)); - $output .= chr(ord('0') + $options['iteration_count_log2'] % 10); - $output .= '$'; - $i = 0; - do { - $c1 = ord($input[$i++]); - $output .= $itoa64[$c1 >> 2]; - $c1 = ($c1 & 0x03) << 4; - if ($i >= 16) { - $output .= $itoa64[$c1]; - break; - } - $c2 = ord($input[$i++]); - $c1 |= $c2 >> 4; - $output .= $itoa64[$c1]; - $c1 = ($c2 & 0x0f) << 2; - $c2 = ord($input[$i++]); - $c1 |= $c2 >> 6; - $output .= $itoa64[$c1]; - $output .= $itoa64[$c2 & 0x3f]; - } while (1); - - return $output; - } -} diff --git a/src/Appwrite/Auth/Hash/Scrypt.php b/src/Appwrite/Auth/Hash/Scrypt.php deleted file mode 100644 index 821b1fba69..0000000000 --- a/src/Appwrite/Auth/Hash/Scrypt.php +++ /dev/null @@ -1,51 +0,0 @@ -getOptions(); - - return \scrypt($password, $options['salt'], $options['costCpu'], $options['costMemory'], $options['costParallel'], $options['length']); - } - - /** - * @param string $password Input password to validate - * @param string $hash Hash to verify password against - * - * @return boolean true if password matches hash - */ - public function verify(string $password, string $hash): bool - { - return $hash === $this->hash($password); - } - - /** - * Get default options for specific hashing algo - * - * @return array options named array - */ - public function getDefaultOptions(): array - { - return [ 'costCpu' => 8, 'costMemory' => 14, 'costParallel' => 1, 'length' => 64 ]; - } -} diff --git a/src/Appwrite/Auth/Hash/Scryptmodified.php b/src/Appwrite/Auth/Hash/Scryptmodified.php deleted file mode 100644 index 7717f324e5..0000000000 --- a/src/Appwrite/Auth/Hash/Scryptmodified.php +++ /dev/null @@ -1,80 +0,0 @@ -getOptions(); - - $derivedKeyBytes = $this->generateDerivedKey($password); - $signerKeyBytes = \base64_decode($options['signerKey']); - - $hashedPassword = $this->hashKeys($signerKeyBytes, $derivedKeyBytes); - - return \base64_encode($hashedPassword); - } - - /** - * @param string $password Input password to validate - * @param string $hash Hash to verify password against - * - * @return boolean true if password matches hash - */ - public function verify(string $password, string $hash): bool - { - return $this->hash($password) === $hash; - } - - /** - * Get default options for specific hashing algo - * - * @return array options named array - */ - public function getDefaultOptions(): array - { - return [ ]; - } - - private function generateDerivedKey(string $password) - { - $options = $this->getOptions(); - - $saltBytes = \base64_decode($options['salt']); - $saltSeparatorBytes = \base64_decode($options['saltSeparator']); - - $password = mb_convert_encoding($password, 'UTF-8'); - $derivedKey = \scrypt($password, $saltBytes . $saltSeparatorBytes, 16384, 8, 1, 64); - $derivedKey = \hex2bin($derivedKey); - - return $derivedKey; - } - - private function hashKeys($signerKeyBytes, $derivedKeyBytes): string - { - $key = \substr($derivedKeyBytes, 0, 32); - - $iv = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; - - $hash = \openssl_encrypt($signerKeyBytes, 'aes-256-ctr', $key, OPENSSL_RAW_DATA, $iv); - - return $hash; - } -} diff --git a/src/Appwrite/Auth/Hash/Sha.php b/src/Appwrite/Auth/Hash/Sha.php deleted file mode 100644 index c2ae3b52c1..0000000000 --- a/src/Appwrite/Auth/Hash/Sha.php +++ /dev/null @@ -1,50 +0,0 @@ -getOptions()['version']; - - return \hash($algo, $password); - } - - /** - * @param string $password Input password to validate - * @param string $hash Hash to verify password against - * - * @return boolean true if password matches hash - */ - public function verify(string $password, string $hash): bool - { - return $this->hash($password) === $hash; - } - - /** - * Get default options for specific hashing algo - * - * @return array options named array - */ - public function getDefaultOptions(): array - { - return [ 'version' => 'sha3-512' ]; - } -}