Improve configuration of cert/key options

This commit is contained in:
Jansen Price 2020-08-26 22:16:05 -05:00
parent 2f6d457235
commit 3c545b1efc
5 changed files with 59 additions and 20 deletions

2
.gitignore vendored
View file

@ -1 +1,3 @@
vendor
*.log
*.pem

View file

@ -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',

View file

@ -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;
}

View file

@ -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();
}

View file

@ -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);