From 3c545b1efca51e9110d10a6a91c76a03536a2c94 Mon Sep 17 00:00:00 2001 From: Jansen Price Date: Wed, 26 Aug 2020 22:16:05 -0500 Subject: [PATCH] Improve configuration of cert/key options --- .gitignore | 2 ++ bin/orbit | 6 ++++-- src/Orbit/Config.php | 5 +++++ src/Orbit/Console.php | 22 +++++++++++++++++++--- src/Orbit/Server.php | 44 ++++++++++++++++++++++++++++--------------- 5 files changed, 59 insertions(+), 20 deletions(-) diff --git a/.gitignore b/.gitignore index 22d0d82..37ce5fa 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ vendor +*.log +*.pem diff --git a/bin/orbit b/bin/orbit index f6db959..d45794a 100755 --- a/bin/orbit +++ b/bin/orbit @@ -8,9 +8,11 @@ require_once dirname(__DIR__) . "/vendor/autoload.php"; $args = new \Qi_Console_ArgV( $argv, [ - 'host|h:' => 'Set host/ip address to listen on (default 0.0.0.0)', + 'host:' => 'Set host/ip address to listen on (default 0.0.0.0)', 'port|p:' => 'Set port to listen on (default 1965)', - 'pem-cert:' => 'Set cert PEM file to use (default ./server.pem)', + 'hostname:' => 'Set hostname of server', + 'tls-cert:' => 'Set cert PEM file to use (default null)', + 'tls-key:' => 'Set private key PEM file to use (default null)', 'log:' => 'Set log filename (default orbit.log)', 'help|h' => 'Show help', 'verbose|v' => 'Include more verbose output', diff --git a/src/Orbit/Config.php b/src/Orbit/Config.php index aed8579..9718983 100644 --- a/src/Orbit/Config.php +++ b/src/Orbit/Config.php @@ -6,8 +6,13 @@ class Config { public $host = "0.0.0.0"; public $port = 1965; + public $hostname = "localhost"; public $log_file = "./orbit.log"; + public $tls_certfile = "./server.cert.pem"; + public $tls_keyfile = "./server.key.pem"; + public $key_passphrase = ""; + public $quiet = false; public $verbose = false; } diff --git a/src/Orbit/Console.php b/src/Orbit/Console.php index e853b27..e1c9489 100644 --- a/src/Orbit/Console.php +++ b/src/Orbit/Console.php @@ -30,6 +30,10 @@ class Console extends \Qi_Console_Client $config->port = $this->_args->port; } + if ($this->_args->hostname) { + $config->hostname = $this->_args->hostname; + } + if ($this->_args->log) { $config->log_file = $this->_args->log; } @@ -42,12 +46,24 @@ class Console extends \Qi_Console_Client $config->verbose = $this->_args->verbose; } + if ($this->_args->get("tls-cert")) { + $config->tls_certfile = $this->_args->get("tls-cert"); + } else { + $config->tls_certfile = sprintf("%s.cert.pem", $config->hostname); + } + + if ($this->_args->get("tls-key")) { + $config->tls_keyfile = $this->_args->get("tls-key"); + } else { + $config->tls_keyfile = sprintf("%s.key.pem", $config->hostname); + } + if (!$config->quiet) { print "Orbit // Gemini server software\n"; + print ":: Using cert file " . $config->tls_certfile . "\n"; + print ":: Using key file " . $config->tls_keyfile . "\n"; } - $server = new Server($config); - - $server->setLogger($this->makeLogger($config)); + $server = new Server($config, $this->makeLogger($config)); $server->listen(); } diff --git a/src/Orbit/Server.php b/src/Orbit/Server.php index 811da65..72688b9 100644 --- a/src/Orbit/Server.php +++ b/src/Orbit/Server.php @@ -10,14 +10,15 @@ class Server public static $version = "0.2"; public $config; - public $pemfile = "./server.pem"; - public $pem_passphrase = ""; + public $tls_certfile = "./server.cert.pem"; + public $tls_keyfile = "./server.key.pem"; + public $key_passphrase = ""; public $timeout = 60; private $ssl_context; private $logger; - public function __construct(Config $config = null) + public function __construct(Config $config = null, Logger $logger = null) { if ($config == null) { $this->config = new Config(); @@ -25,12 +26,22 @@ class Server $this->config = $config; } + if ($logger !== null) { + $this->setLogger($logger); + } + $this->timeout = ini_get("default_socket_timeout"); - if (file_exists($this->pemfile)) { - $this->log(Logger::DEBUG, "Using existing cert."); + if (file_exists($this->config->tls_certfile) && file_exists($this->config->tls_keyfile)) { + $this->log(Logger::DEBUG, "Using existing cert + key."); } else { $this->log(Logger::DEBUG, "Generating new cert."); + if (file_exists($this->config->tls_certfile)) { + $this->log(Logger::WARNING, "Warning! May overwrite existing cert file '" . $this->config->tls_certfile . "'\n"); + } + if (file_exists($this->config->tls_keyfile)) { + $this->log(Logger::WARNING, "Warning! May overwrite existing key file '" . $this->config->tls_keyfile . "'\n"); + } $this->generateCert(); } $this->ssl_context = $this->createSslContext(); @@ -66,7 +77,7 @@ class Server $protocol = "gemini"; $name = stream_socket_get_name($server, false); - $this->log(Logger::NOTICE, "Listening on $protocol://$name ..."); + $this->log(Logger::INFO, "Listening on $protocol://$name ..."); while (true) { # This is to swallow up the `timeout` warning @@ -100,9 +111,11 @@ class Server // Do nothing return; } + $error = sprintf("Error %s: %s", $id, $message); + $this->log(Logger::ERROR, "$client_name Closed"); // Something else happened. - throw new \Exception($id . ' ' . $message); + throw new \Exception($error); } public function getListenAddress() @@ -119,7 +132,7 @@ class Server "localityName" => "X", "organizationName" => "X", "organizationalUnitName" => "X", - "commonName" => "orbit1.0", + "commonName" => $this->config->hostname, "emailAddress" => "X" ]; @@ -128,14 +141,14 @@ class Server $cert = openssl_csr_new($dn, $privkey); $cert = openssl_csr_sign($cert, null, $privkey, 365); - // Generate PEM file + // Generate PEM files $pem = []; openssl_x509_export($cert, $pem[0]); - openssl_pkey_export($privkey, $pem[1], $this->pem_passphrase); - $pem = implode($pem); + openssl_pkey_export($privkey, $pem[1], $this->config->key_passphrase); - // Save PEM file - file_put_contents($this->pemfile, $pem); + // Save PEM files + file_put_contents($this->config->tls_certfile, $pem[0]); + file_put_contents($this->config->tls_keyfile, $pem[1]); } public function createSslContext() @@ -143,8 +156,9 @@ class Server $context = stream_context_create(); // local_cert must be in PEM format - stream_context_set_option($context, 'ssl', 'local_cert', $this->pemfile); - stream_context_set_option($context, 'ssl', 'passphrase', $this->pem_passphrase); + stream_context_set_option($context, 'ssl', 'local_cert', $this->config->tls_certfile); + stream_context_set_option($context, 'ssl', 'local_pk', $this->config->tls_keyfile); + stream_context_set_option($context, 'ssl', 'passphrase', $this->config->key_passphrase); stream_context_set_option($context, 'ssl', 'allow_self_signed', true); stream_context_set_option($context, 'ssl', 'verify_peer', false);