From 881befccfa7c8533cddb3c3cc2382925d137991f Mon Sep 17 00:00:00 2001 From: Jansen Price Date: Thu, 3 Sep 2020 14:11:09 -0500 Subject: [PATCH] Update dependencies - add Encoding --- composer.json | 3 +- composer.lock | 39 ++++++++++++++++- src/Orbit/Cert.php | 2 +- src/Orbit/Console.php | 4 +- src/Orbit/Server.php | 99 +++++++++++++++++++++++++++++++++++++------ 5 files changed, 129 insertions(+), 18 deletions(-) diff --git a/composer.json b/composer.json index 6a95eae..c21026f 100644 --- a/composer.json +++ b/composer.json @@ -10,7 +10,8 @@ ], "require": { "sumpygump/qi-console": "^1.3", - "monolog/monolog": "^2.1" + "monolog/monolog": "^2.1", + "neitanod/forceutf8": "^2.0" }, "autoload": { "psr-4" : { diff --git a/composer.lock b/composer.lock index 92277c3..2c822d8 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "f2158d38eb2be637af2512ebe8b515b2", + "content-hash": "8a62de9c76733e8532666218b31a1e94", "packages": [ { "name": "monolog/monolog", @@ -97,6 +97,43 @@ ], "time": "2020-07-23T08:41:23+00:00" }, + { + "name": "neitanod/forceutf8", + "version": "v2.0.4", + "source": { + "type": "git", + "url": "https://github.com/neitanod/forceutf8.git", + "reference": "c1fbe70bfb5ad41b8ec5785056b0e308b40d4831" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/neitanod/forceutf8/zipball/c1fbe70bfb5ad41b8ec5785056b0e308b40d4831", + "reference": "c1fbe70bfb5ad41b8ec5785056b0e308b40d4831", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "autoload": { + "psr-0": { + "ForceUTF8\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastián Grignoli", + "email": "grignoli@gmail.com" + } + ], + "description": "PHP Class Encoding featuring popular Encoding::toUTF8() function --formerly known as forceUTF8()-- that fixes mixed encoded strings.", + "homepage": "https://github.com/neitanod/forceutf8", + "time": "2019-12-10T14:09:14+00:00" + }, { "name": "psr/log", "version": "1.1.3", diff --git a/src/Orbit/Cert.php b/src/Orbit/Cert.php index 3791d72..68ae6b7 100644 --- a/src/Orbit/Cert.php +++ b/src/Orbit/Cert.php @@ -116,7 +116,7 @@ class Cert ]; $days_valid = 365; - $san_domains = ["DNS:" . $this->hostname, "IP:127.0.0.1", "IP:0.0.0.0"]; + $san_domains = ["DNS:" . $this->hostname, "IP:127.0.0.1", "IP:0.0.0.0", "IP:::1"]; $ssl_config = $this->createOpenSslConf($san_domains); $csr_config = ['digest_alg' => 'sha256', 'req_extensions' => 'v3_req', 'config' => $ssl_config]; diff --git a/src/Orbit/Console.php b/src/Orbit/Console.php index 8a00e5f..38096b9 100644 --- a/src/Orbit/Console.php +++ b/src/Orbit/Console.php @@ -45,11 +45,11 @@ class Console extends \Qi_Console_Client $config->readFromIniFile($this->_args->config); } - if ($this->_args->host) { + if ($this->_args->host || $this->_args->host == "0") { $config->host = $this->_args->host; } - if ($this->_args->port) { + if ($this->_args->port || $this->_args->port == "0") { $config->port = $this->_args->port; } diff --git a/src/Orbit/Server.php b/src/Orbit/Server.php index 40512b7..d166b1d 100644 --- a/src/Orbit/Server.php +++ b/src/Orbit/Server.php @@ -4,6 +4,7 @@ namespace Orbit; use Monolog\Logger; use Monolog\Handler\StreamHandler; +use ForceUTF8\Encoding; class Server { @@ -70,6 +71,7 @@ class Server $this->logger->debug("Root directory '$path'"); + var_dump($this->getListenAddress()); $server = stream_socket_server( $this->getListenAddress(), $errno, $errstr, @@ -89,24 +91,30 @@ class Server # This is to swallow up the `timeout` warning set_error_handler([$this, 'onWarning']); $client = stream_socket_accept($server, $this->timeout, $client_name); + //stream_socket_enable_crypto($server, true, STREAM_CRYPTO_METHOD_TLSv1_2_SERVER); restore_error_handler(); if ($client) { $time = ['start' => microtime(true)]; $this->logger->debug("$client_name Accepted"); - $request_buffer = stream_get_line($client, 1024, "\r\n"); + $request_buffer = stream_get_line($client, 1026, "\r\n"); + print($this->hexView($request_buffer)); + print("Length: " . mb_strlen($request_buffer) . "\n"); $this->logger->info("REQ: $request_buffer", ["client" => $client_name]); - $request = new Request($request_buffer); - // Respond to client - $response = $this->handleResponse($request, $path); - $size = $response->send($client); - $time['end'] = microtime(true); - $this->logger->debug( - "RSP: " . trim($response->getHeader()), - ['size' => $size, 'time' => $time['end'] - $time['start']] - ); + if (trim($request_buffer)) { + $request = new Request($request_buffer); + + // Respond to client + $response = $this->handleResponse($request, $path); + $size = $response->send($client); + $time['end'] = microtime(true); + $this->logger->debug( + "RSP: " . trim($response->getHeader()), + ['size' => $size, 'time' => $time['end'] - $time['start']] + ); + } fclose($client); $this->logger->debug("$client_name Closed"); @@ -116,9 +124,38 @@ class Server public function handleResponse($request, $dir) { + $response = new Response(); + + // Valid URL must not be more than 1024 chars + if (mb_strlen($request->url) > 1024) { + $response->setStatus(Response::STATUS_BAD_REQUEST); + $response->setMeta("Bad request - too long"); + return $response; + } + + if ($request->host != "127.0.0.1" && $request->host != $this->config->hostname) { + $response->setStatus(Response::STATUS_PROXY_REQUEST_REFUSED); + $response->setMeta("Proxy error - invalid host"); + return $response; + } + + // Valid URL must use correct port + if ($request->port != "" && $request->port != $this->config->port) { + $response->setStatus(Response::STATUS_PROXY_REQUEST_REFUSED); + $response->setMeta("Proxy error - invalid port"); + return $response; + } + + // Valid URL must not contain non-UTF-8 bytes + $conv = Encoding::fixUTF8($request->url); + if ($conv != $request->url) { + $response->setStatus(Response::STATUS_BAD_REQUEST); + $response->setMeta("Bad request - non-UTF8"); + return $response; + } + $resource_path = rtrim($dir, "/") . $request->path; - $response = new Response(); if (is_dir($resource_path)) { // If missing the final slash, issue a redirect if ($resource_path[-1] != "/") { @@ -185,9 +222,8 @@ class Server } // Something else happened. - $error = sprintf("Error %s: %s", $id, $message); + $error = sprintf("Error while accepting connection %s: %s", $id, $message); $this->logger->error($error); - throw new \Exception($error); } public function getListenAddress() @@ -240,4 +276,41 @@ class Server return $context; } + + /** + * View hex chars of string + * + * Outputs a listing of hexidecimal values in 16 byte rows + * + * @param mixed $text Input text + * @return string + */ + private function hexView($text) + { + $num = 16; + $outStr = ''; + $printableChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + . 'abcdefghijklmnopqrstuvwxyz' + . '0123456789~!@#$%^&*()_+-={}|[]\:";\'<>?,./'; + + $charCount = strlen($text); + for ($i = 0; $i < $charCount; $i += $num) { + $printStr = ''; + for ($j = 0; $j < $num; $j++) { + $char = substr($text, $i+$j, 1); + + $outStr .= sprintf("%02X", ord($char)) . " "; + + if (ord($char) >= 32 && ord($char) < 127) { + $printStr .= $char; + } else { + $printStr .= "."; + } + } + + $outStr .= " | " . $printStr . "\n"; + } + + return $outStr; + } }