aboutsummaryrefslogtreecommitdiffstats
path: root/modules/websocket.cpp
diff options
context:
space:
mode:
authorGravatar Sadie Powell2024-07-22 21:26:45 +0100
committerGravatar Sadie Powell2024-07-22 21:26:45 +0100
commit304ad49279362eb9d3d28468e8e84a9ab0d9f119 (patch)
tree0c2ef51b4e968f309a33b6c7975e00cb7954225a /modules/websocket.cpp
parentAdjust the build system for the new module structure. (diff)
parentFix shadowing messages in pgsql and regex_pcre2. (diff)
Merge branch 'insp4' into master.
Diffstat (limited to 'modules/websocket.cpp')
-rw-r--r--modules/websocket.cpp32
1 files changed, 28 insertions, 4 deletions
diff --git a/modules/websocket.cpp b/modules/websocket.cpp
index 8119f30c6..d0f035b72 100644
--- a/modules/websocket.cpp
+++ b/modules/websocket.cpp
@@ -23,6 +23,7 @@
#include "inspircd.h"
#include "iohook.h"
#include "modules/hash.h"
+#include "modules/isupport.h"
#include "utility/string.h"
#define UTF_CPP_CPLUSPLUS 199711L
@@ -53,6 +54,9 @@ struct WebSocketConfig final
// The HTTP origins that can connect to the server.
OriginList allowedorigins;
+ // Whether text encoding can be used on this server.
+ bool allowtext;
+
// The method to use if a subprotocol is not negotiated.
DefaultMode defaultmode;
@@ -468,9 +472,8 @@ class WebSocketHook final
{
std::erase_if(proto, ::isspace);
- bool is_binary = insp::equalsci(proto, "binary.inspircd.org");
- bool is_text = insp::equalsci(proto, "text.inspircd.org");
-
+ auto is_binary = insp::equalsci(proto, "binary.ircv3.net");
+ auto is_text = insp::equalsci(proto, "text.ircv3.net");
if (is_binary || is_text)
{
selectedproto = std::move(proto);
@@ -486,6 +489,12 @@ class WebSocketHook final
return -1;
}
+ if (sendastext && !config.allowtext)
+ {
+ FailHandshake(sock, "HTTP/1.1 400 Bad Request\r\nConnection: close\r\n\r\n", "WebSocket: Received HTTP request that requested a text protocol which is not compatible with the server character set");
+ return -1;
+ }
+
HTTPHeaderFinder keyheader;
if (!keyheader.Find(recvq, "Sec-WebSocket-Key:", 18, reqend))
{
@@ -628,12 +637,14 @@ class ModuleWebSocket final
private:
dynamic_reference_nocheck<HashProvider> hash;
std::shared_ptr<WebSocketHookProvider> hookprov;
+ ISupport::EventProvider isupportprov;
public:
ModuleWebSocket()
: Module(VF_VENDOR, "Allows WebSocket clients to connect to the IRC server.")
, hash(this, "hash/sha1")
, hookprov(std::make_shared<WebSocketHookProvider>(this))
+ , isupportprov(this)
{
sha1 = &hash;
}
@@ -645,6 +656,16 @@ public:
throw ModuleException(this, "You have loaded the websocket module but not configured any allowed origins!");
WebSocketConfig config;
+
+ // If a server has a non-utf8 compatible character set configured
+ // then we can not support text encoding.
+ ISupport::TokenMap tokens;
+ isupportprov.Call(&ISupport::EventListener::OnBuildISupport, tokens);
+ auto it = tokens.find("CHARSET");
+ config.allowtext = it == tokens.end()
+ || irc::equals(it->second, "ascii")
+ || irc::equals(it->second, "utf8");
+
for (const auto& [_, tag] : tags)
{
// Ensure that we have the <wsorigin:allow> parameter.
@@ -657,7 +678,7 @@ public:
const auto& tag = ServerInstance->Config->ConfValue("websocket");
- const std::string defaultmodestr = tag->getString("defaultmode", "text", 1);
+ const std::string defaultmodestr = tag->getString("defaultmode", config.allowtext ? "text" : "binary", 1);
if (insp::equalsci(defaultmodestr, "reject"))
config.defaultmode = WebSocketConfig::DM_REJECT;
else if (insp::equalsci(defaultmodestr, "binary"))
@@ -667,6 +688,9 @@ public:
else
throw ModuleException(this, defaultmodestr + " is an invalid value for <websocket:defaultmode>; acceptable values are 'binary', 'text' and 'reject', at " + tag->source.str());
+ if (config.defaultmode == WebSocketConfig::DM_TEXT && !config.allowtext)
+ throw ModuleException(this, "You can not use text websockets when using a non-utf8 compatible server charset, at " + tag->source.str());
+
irc::spacesepstream proxyranges(tag->getString("proxyranges"));
for (std::string proxyrange; proxyranges.GetToken(proxyrange); )
config.proxyranges.push_back(proxyrange);