Skip to content
Permalink
Browse files

Added SetAllowedOrigins() to restrict allowed Origin headers.

  • Loading branch information...
cubiclesoft committed May 5, 2019
1 parent 2f3ab74 commit 5f72caf4f4ce401625d43251ef41866c13197717
Showing with 41 additions and 8 deletions.
  1. +13 −0 docs/websocket_server.md
  2. +28 −8 websocket_server.php
@@ -39,6 +39,19 @@ Returns: Nothing.

This function assigns a new class name of the instance of a class to allocate. The default is "WebSocket" and the specified class must extend WebSocket or there will be problems later on when clients connect in.

WebSocketServer::SetAllowedOrigins($origins)
--------------------------------------------

Access: public

Parameters:

* $origins - A string or an array containing allowed Origin header(s) or a boolean of false to allow any Origin header.

Returns: Nothing.

This function assigns allowed Origin HTTP header strings. Useful for validating client connections to the WebSocket server when it is public-facing to the Internet or made available via a proxy. Can be spoofed but can prevent XSRF attacks in real web browsers that do send valid Origin header strings.

WebSocketServer::SetDefaultCloseMode($mode)
-------------------------------------------

@@ -9,7 +9,7 @@
// Requires the CubicleSoft PHP WebSocket class.
class WebSocketServer
{
private $fp, $clients, $nextclientid, $websocketclass;
private $fp, $clients, $nextclientid, $websocketclass, $origins;
private $defaultclosemode, $defaultmaxreadframesize, $defaultmaxreadmessagesize, $defaultkeepalive;
public function __construct()
@@ -25,6 +25,7 @@ public function Reset()
$this->clients = array();
$this->nextclientid = 1;
$this->websocketclass = "WebSocket";
$this->origins = false;
$this->defaultclosemode = WebSocket::CLOSE_IMMEDIATELY;
$this->defaultmaxreadframesize = 2000000;
@@ -42,6 +43,15 @@ public function SetWebSocketClass($newclass)
if (class_exists($newclass)) $this->websocketclass = $newclass;
}
public function SetAllowedOrigins($origins)
{
if (is_string($origins)) $origins = array($origins);
if (!is_array($origins)) $origins = false;
else if (isset($origins[0])) $origins = array_flip($origins);
$this->origins = $origins;
}
public function SetDefaultCloseMode($mode)
{
$this->defaultclosemode = $mode;
@@ -108,18 +118,18 @@ protected function ProcessNewConnection($method, $path, $client)
{
$result = "";
if ($method !== "GET") $result .= "HTTP/1.1 405 Method Not Allowed\r\n\r\n";
if ($method !== "GET") $result .= "HTTP/1.1 405 Method Not Allowed\r\nConnection: close\r\n\r\n";
else if (!isset($client->headers["Host"]) || !isset($client->headers["Connection"]) || stripos($client->headers["Connection"], "upgrade") === false || !isset($client->headers["Upgrade"]) || stripos($client->headers["Upgrade"], "websocket") === false || !isset($client->headers["Sec-Websocket-Key"]))
{
$result .= "HTTP/1.1 400 Bad Request\r\n\r\n";
$result .= "HTTP/1.1 400 Bad Request\r\nConnection: close\r\n\r\n";
}
else if (!isset($client->headers["Sec-Websocket-Version"]) || $client->headers["Sec-Websocket-Version"] != 13)
{
$result .= "HTTP/1.1 426 Upgrade Required\r\nSec-WebSocket-Version: 13\r\n\r\n";
$result .= "HTTP/1.1 426 Upgrade Required\r\nSec-WebSocket-Version: 13\r\nConnection: close\r\n\r\n";
}
else if (!isset($client->headers["Origin"]))
else if (!isset($client->headers["Origin"]) || ($this->origins !== false && !isset($this->origins[strtolower($client->headers["Origin"])])))
{
$result .= "HTTP/1.1 403 Forbidden\r\n\r\n";
$result .= "HTTP/1.1 403 Forbidden\r\nConnection: close\r\n\r\n";
}
return $result;
@@ -145,6 +155,7 @@ protected function InitNewClient($fp)
$client->lastheader = "";
$client->websocket = false;
$client->fp = $fp;
$client->ipaddr = stream_socket_get_name($fp, true);
// Intended for application storage.
$client->appdata = false;
@@ -403,8 +414,17 @@ public function Wait($timeout = false, $readfps = array(), $writefps = array(),
{
$client->writedata = (string)substr($client->writedata, $result2);
// Let the application know about the new client.
if ($client->writedata === "") $result["clients"][$id] = $client;
// Let the application know about the new client or close the connection if the WebSocket Upgrade request failed.
if ($client->writedata === "")
{
if ($client->websocket->GetStream() !== false) $result["clients"][$id] = $client;
else
{
@fclose($fp);
unset($this->clients[$id]);
}
}
}
}

0 comments on commit 5f72caf

Please sign in to comment.
You can’t perform that action at this time.