From 658f683cbeb993132acaed0c1135f60cd1320815 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=BCck?= Date: Fri, 27 Jan 2017 15:28:23 +0100 Subject: [PATCH 1/2] Reject listening on hostnames and document valid URIs --- README.md | 33 ++++++++++++++++++++++++---- src/Server.php | 37 +++++++++++++++++++++++++++---- tests/FunctionalServerTest.php | 40 ++++++++++++++++++++++++++++++++++ 3 files changed, 102 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 12ed7776..e97c07a0 100644 --- a/README.md +++ b/README.md @@ -151,15 +151,40 @@ is responsible for accepting plaintext TCP/IP connections. $server = new Server(8080, $loop); ``` -By default, the server will listen on the localhost address and will not be -reachable from the outside. -You can change the host the socket is listening on through a first parameter -provided to the constructor: +As above, the `$uri` parameter can consist of only a port, in which case the +server will default to listening on the localhost address `127.0.0.1` and thus +it will not be reachable from outside of this system. + +In order to use a random port assignment, you can use the port `0`: + +```php +$server = new Server(0, $loop); +$port = $server->getPort(); +``` + +In order to change the host the socket is listening on, you can provide an IP +addres through the first parameter provided to the constructor, optionally +preceded by the `tcp://` scheme: ```php $server = new Server('192.168.0.1:8080', $loop); ``` +If you want to listen on an IPv6 address, you MUST enclose the host in square +brackets: + +```php +$server = new Server('[::1]:8080', $loop); +``` + +If the given URI is invalid, does not contain a port, any other scheme or if it +contains a hostname, it will throw an `InvalidArgumentException`: + +```php +// throws InvalidArgumentException due to missing port +$server = new Server('127.0.0.1', $loop); +``` + Optionally, you can specify [socket context options](http://php.net/manual/en/context.socket.php) for the underlying stream socket resource like this: diff --git a/src/Server.php b/src/Server.php index fd7341a6..6d9b09d0 100644 --- a/src/Server.php +++ b/src/Server.php @@ -50,15 +50,40 @@ class Server extends EventEmitter implements ServerInterface * $server = new Server(8080, $loop); * ``` * - * By default, the server will listen on the localhost address and will not be - * reachable from the outside. - * You can change the host the socket is listening on through the first parameter - * provided to the constructor. + * As above, the `$uri` parameter can consist of only a port, in which case the + * server will default to listening on the localhost address `127.0.0.1` and thus + * it will not be reachable from outside of this system. + * + * In order to use a random port assignment, you can use the port `0`: + * + * ```php + * $server = new Server(0, $loop); + * $port = $server->getPort(); + * ``` + * + * In order to change the host the socket is listening on, you can provide an IP + * addres through the first parameter provided to the constructor, optionally + * preceded by the `tcp://` scheme: * * ```php * $server = new Server('192.168.0.1:8080', $loop); * ``` * + * If you want to listen on an IPv6 address, you MUST enclose the host in square + * brackets: + * + * ```php + * $server = new Server('[::1]:8080', $loop); + * ``` + * + * If the given URI is invalid, does not contain a port, any other scheme or if it + * contains a hostname, it will throw an `InvalidArgumentException`: + * + * ```php + * // throws InvalidArgumentException due to missing port + * $server = new Server('127.0.0.1', $loop); + * ``` + * * Optionally, you can specify [socket context options](http://php.net/manual/en/context.socket.php) * for the underlying stream socket resource like this: * @@ -110,6 +135,10 @@ public function __construct($uri, LoopInterface $loop, array $context = array()) throw new InvalidArgumentException('Invalid URI "' . $uri . '" given'); } + if (false === filter_var(trim($parts['host'], '[]'), FILTER_VALIDATE_IP)) { + throw new \InvalidArgumentException('Given URI "' . $uri . '" does not contain a valid host IP'); + } + $this->master = @stream_socket_server( $uri, $errno, diff --git a/tests/FunctionalServerTest.php b/tests/FunctionalServerTest.php index 96ac11bf..8b993906 100644 --- a/tests/FunctionalServerTest.php +++ b/tests/FunctionalServerTest.php @@ -175,4 +175,44 @@ public function testAppliesContextOptionsToSocketStreamResource() $this->assertEquals(array('socket' => array('backlog' => 4)), $all); } + + /** + * @expectedException InvalidArgumentException + */ + public function testFailsToListenOnInvalidUri() + { + $loop = Factory::create(); + + new Server('///', $loop); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testFailsToListenOnUriWithoutPort() + { + $loop = Factory::create(); + + new Server('127.0.0.1', $loop); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testFailsToListenOnUriWithWrongScheme() + { + $loop = Factory::create(); + + new Server('udp://127.0.0.1:0', $loop); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testFailsToListenOnUriWIthHostname() + { + $loop = Factory::create(); + + new Server('localhost:8080', $loop); + } } From 33a70048f5b5e384362007649245e6808632564d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=BCck?= Date: Sat, 28 Jan 2017 17:08:32 +0100 Subject: [PATCH 2/2] Fugbix typo. --- README.md | 6 +++--- src/Server.php | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index e97c07a0..19da8ad8 100644 --- a/README.md +++ b/README.md @@ -152,8 +152,8 @@ $server = new Server(8080, $loop); ``` As above, the `$uri` parameter can consist of only a port, in which case the -server will default to listening on the localhost address `127.0.0.1` and thus -it will not be reachable from outside of this system. +server will default to listening on the localhost address `127.0.0.1`, +which means it will not be reachable from outside of this system. In order to use a random port assignment, you can use the port `0`: @@ -163,7 +163,7 @@ $port = $server->getPort(); ``` In order to change the host the socket is listening on, you can provide an IP -addres through the first parameter provided to the constructor, optionally +address through the first parameter provided to the constructor, optionally preceded by the `tcp://` scheme: ```php diff --git a/src/Server.php b/src/Server.php index 6d9b09d0..8f6452ee 100644 --- a/src/Server.php +++ b/src/Server.php @@ -51,8 +51,8 @@ class Server extends EventEmitter implements ServerInterface * ``` * * As above, the `$uri` parameter can consist of only a port, in which case the - * server will default to listening on the localhost address `127.0.0.1` and thus - * it will not be reachable from outside of this system. + * server will default to listening on the localhost address `127.0.0.1`, + * which means it will not be reachable from outside of this system. * * In order to use a random port assignment, you can use the port `0`: * @@ -62,7 +62,7 @@ class Server extends EventEmitter implements ServerInterface * ``` * * In order to change the host the socket is listening on, you can provide an IP - * addres through the first parameter provided to the constructor, optionally + * address through the first parameter provided to the constructor, optionally * preceded by the `tcp://` scheme: * * ```php