xp-forge / xp-forge/web

Add SSL support

Open
#78 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

question security
Dominant language
PHP
Stars
2
Forks
1
PR merge metrics
No merged PRs in 30d

Description

Proof of concept

Adding a second socket with ssl context options:

diff --git a/src/main/php/xp/web/srv/Standalone.class.php b/src/main/php/xp/web/srv/Standalone.class.php
index 0e5be20..3d4dccf 100755
--- a/src/main/php/xp/web/srv/Standalone.class.php
+++ b/src/main/php/xp/web/srv/Standalone.class.php
@@ -30,12 +30,27 @@ abstract class Standalone implements Server {
     $environment= new Environment($profile, $webroot, $docroot, $config, $args, $logging);
     $application= (new Source($source, $environment))->application($args);
     $application->routing();
+    $protocol= new HttpProtocol($application, $environment->logging());
+
+    $http= new ServerSocket($this->host, $this->port);
+    $this->server->listen($http, $protocol);
+
+    // TODO: Remove hardcoded port and certificates, fetch from command line arguments
+    $https= new class($this->host, 8443) extends ServerSocket {
+      public function listen($backlog= SOMAXCONN) {
+        $this->setSocketOption('ssl', 'allow_self_signed', true);
+        $this->setSocketOption('ssl', 'disable_compression', true);
+        $this->setSocketOption('ssl', 'verify_peer', false);
+        $this->setSocketOption('ssl', 'local_cert', 'localhost.crt');
+        $this->setSocketOption('ssl', 'local_pk', 'localhost.key');
+        parent::listen($backlog);
+      }
+    };
+    $this->server->listen($https, new SSL($protocol));
 
-    $socket= new ServerSocket($this->host, $this->port);
-    $this->server->listen($socket, new HttpProtocol($application, $environment->logging()));
     $this->server->init();
 
-    Console::writeLine("\e[33m@", nameof($this), '(HTTP @ ', $socket->toString(), ")\e[0m");
+    Console::writeLine("\e[33m@", nameof($this), '(HTTP @ ', $http->toString(), ")\e[0m");
     Console::writeLine("\e[1mServing ", $application, $config, "\e[0m > ", $environment->logging()->target());
     Console::writeLine("\e[36m", str_repeat('═', 72), "\e[0m");
 

...and wrapping the protocol in this class:

<?php namespace xp\web\srv;

use peer\server\ServerProtocol;
use peer\server\protocol\SocketAcceptHandler;

/**
 * HTTPS transport
 *
 * @see  https://github.com/FiloSottile/mkcert
 * @see  https://letsencrypt.org/docs/certificates-for-localhost/
 */
class SSL implements ServerProtocol, SocketAcceptHandler {
  private $underlying;

  public function __construct(ServerProtocol $underlying) {
    $this->underlying= $underlying;
  }

  /**
   * Initialize Protocol
   *
   * @return bool
   */
  public function initialize() {
    return $this->underlying->initialize();
  }

  /**
   * Handle client connect
   *
   * @param  peer.Socket $socket
   * @return bool
   */
  public function handleAccept($socket) {
    return stream_socket_enable_crypto(
      $socket->getHandle(),
      true,
      STREAM_CRYPTO_METHOD_TLS_SERVER
    );
  }

  /**
   * Handle client connect
   *
   * @param  peer.Socket $socket
   * @return void
   */
  public function handleConnect($socket) {
    $this->underlying->handleConnect($socket);
  }

  /**
   * Handle client disconnect
   *
   * @param  peer.Socket $socket
   * @return void
   */
  public function handleDisconnect($socket) {
    $this->underlying->handleDisconnect($socket);
  }

  /**
   * Handle client data
   *
   * @param  peer.Socket $socket
   * @return ?iterable
   */
  public function handleData($socket) {
    return $this->underlying->handleData($socket);
  }

  /**
   * Handle I/O error
   *
   * @param  peer.Socket $socket
   * @param  lang.XPException $e
   * @return void
   */
  public function handleError($socket, $e) {
    $this->underlying->handleError($socket, $e);
  }
}

Both include hints as to where our sockets API in xp-framework/networking is not sufficient yet.

Limitations

This only works for standalone webservers - default, async, fork, prefork - and the ext/sockets version might not be trivial. For the development webserver, we would need to implement a proxy.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with src/main/php/xp/web/srv/Standalone.class.php and the proposed SSL protocol wrapper, then inspect the sockets API in xp-framework/networking. Compare the proof of concept with the listed standalone server modes and the development webserver limitation. Done means the scope and integration approach for SSL support are resolved across the applicable servers.

Written by the indexing model from the issue text.

Assessment

Tech stack
php
Domain
backend, networking, security
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.