aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Sadie Powell2021-09-23 00:24:36 +0100
committerGravatar Sadie Powell2021-09-23 00:24:36 +0100
commitb5d7c564282f0b25458c3ca9dbd6aa9eec7d60d5 (patch)
treef4b687e3ca0c5edfefd3ae7cdd3329012a603486 /src
parentMerge branch 'insp3' into master. (diff)
parentUse CXX11_OVERRIDE instead of the override keyword. (diff)
Merge branch 'insp3' into master.
Diffstat (limited to 'src')
-rw-r--r--src/modules/extra/m_ssl_gnutls.cpp22
-rw-r--r--src/modules/extra/m_ssl_mbedtls.cpp31
-rw-r--r--src/modules/extra/m_ssl_openssl.cpp34
-rw-r--r--src/modules/m_haproxy.cpp5
-rw-r--r--src/modules/m_repeat.cpp3
-rw-r--r--src/modules/m_websocket.cpp46
6 files changed, 83 insertions, 58 deletions
diff --git a/src/modules/extra/m_ssl_gnutls.cpp b/src/modules/extra/m_ssl_gnutls.cpp
index bb90538f7..79a9747d6 100644
--- a/src/modules/extra/m_ssl_gnutls.cpp
+++ b/src/modules/extra/m_ssl_gnutls.cpp
@@ -53,8 +53,6 @@
# pragma comment(lib, "libgnutls-30.lib")
#endif
-enum issl_status { ISSL_NONE, ISSL_HANDSHAKING, ISSL_HANDSHAKEN };
-
#if INSPIRCD_GNUTLS_HAS_VERSION(3, 3, 5)
#define INSPIRCD_GNUTLS_HAS_RECV_PACKET
#endif
@@ -611,7 +609,6 @@ class GnuTLSIOHook : public SSLIOHook
{
private:
gnutls_session_t sess = nullptr;
- issl_status status = ISSL_NONE;
#ifdef INSPIRCD_GNUTLS_HAS_CORK
size_t gbuffersize = 0;
#endif
@@ -625,7 +622,7 @@ class GnuTLSIOHook : public SSLIOHook
}
sess = NULL;
certificate = NULL;
- status = ISSL_NONE;
+ status = STATUS_NONE;
}
// Returns 1 if handshake succeeded, 0 if it is still in progress, -1 if it failed
@@ -638,7 +635,7 @@ class GnuTLSIOHook : public SSLIOHook
if(ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED)
{
// Handshake needs resuming later, read() or write() would have blocked.
- this->status = ISSL_HANDSHAKING;
+ this->status = STATUS_HANDSHAKING;
if (gnutls_record_get_direction(this->sess) == 0)
{
@@ -663,7 +660,7 @@ class GnuTLSIOHook : public SSLIOHook
else
{
// Change the session state
- this->status = ISSL_HANDSHAKEN;
+ this->status = STATUS_OPEN;
VerifyCertificate();
@@ -765,9 +762,9 @@ info_done_dealloc:
// Returns 1 if application I/O should proceed, 0 if it must wait for the underlying protocol to progress, -1 on fatal error
int PrepareIO(StreamSocket* sock)
{
- if (status == ISSL_HANDSHAKEN)
+ if (status == STATUS_OPEN)
return 1;
- else if (status == ISSL_HANDSHAKING)
+ else if (status == STATUS_HANDSHAKING)
{
// The handshake isn't finished, try to finish it
return Handshake(sock);
@@ -915,7 +912,7 @@ info_done_dealloc:
if (prepret <= 0)
return prepret;
- // If we resumed the handshake then this->status will be ISSL_HANDSHAKEN.
+ // If we resumed the handshake then this->status will be STATUS_OPEN.
{
GnuTLS::DataReader reader(sess);
ssize_t ret = reader.ret();
@@ -1011,7 +1008,7 @@ info_done_dealloc:
void GetCiphersuite(std::string& out) const override
{
- if (!IsHandshakeDone())
+ if (!IsHookReady())
return;
out.append(UnknownIfNULL(gnutls_protocol_get_name(gnutls_protocol_get_version(sess)))).push_back('-');
out.append(UnknownIfNULL(gnutls_kx_get_name(gnutls_kx_get(sess)))).push_back('-');
@@ -1039,7 +1036,6 @@ info_done_dealloc:
}
GnuTLS::Profile& GetProfile();
- bool IsHandshakeDone() const { return (status == ISSL_HANDSHAKEN); }
};
int GnuTLS::X509Credentials::cert_callback(gnutls_session_t sess, const gnutls_datum_t* req_ca_rdn, int nreqs, const gnutls_pk_algorithm_t* sign_algos, int sign_algos_length, gnutls_retr2_st* st)
@@ -1181,7 +1177,7 @@ class ModuleSSLGnuTLS : public Module
}
catch (ModuleException& ex)
{
- ServerInstance->Logs.Log(MODNAME, LOG_DEFAULT, ex.GetReason() + " Not applying settings.");
+ ServerInstance->SNO.WriteToSnoMask('a', "Failed to reload the GnuTLS TLS (SSL) profiles. " + ex.GetReason());
}
}
@@ -1208,7 +1204,7 @@ class ModuleSSLGnuTLS : public Module
ModResult OnCheckReady(LocalUser* user) override
{
const GnuTLSIOHook* const iohook = static_cast<GnuTLSIOHook*>(user->eh.GetModHook(this));
- if ((iohook) && (!iohook->IsHandshakeDone()))
+ if ((iohook) && (!iohook->IsHookReady()))
return MOD_RES_DENY;
return MOD_RES_PASSTHRU;
}
diff --git a/src/modules/extra/m_ssl_mbedtls.cpp b/src/modules/extra/m_ssl_mbedtls.cpp
index 2c95da3c7..9c025ad56 100644
--- a/src/modules/extra/m_ssl_mbedtls.cpp
+++ b/src/modules/extra/m_ssl_mbedtls.cpp
@@ -523,25 +523,18 @@ namespace mbedTLS
class mbedTLSIOHook : public SSLIOHook
{
- enum Status
- {
- ISSL_NONE,
- ISSL_HANDSHAKING,
- ISSL_HANDSHAKEN
- };
-
+ private:
mbedtls_ssl_context sess;
- Status status;
void CloseSession()
{
- if (status == ISSL_NONE)
+ if (status == STATUS_NONE)
return;
mbedtls_ssl_close_notify(&sess);
mbedtls_ssl_free(&sess);
certificate = NULL;
- status = ISSL_NONE;
+ status = STATUS_NONE;
}
// Returns 1 if handshake succeeded, 0 if it is still in progress, -1 if it failed
@@ -551,7 +544,7 @@ class mbedTLSIOHook : public SSLIOHook
if (ret == 0)
{
// Change the session state
- this->status = ISSL_HANDSHAKEN;
+ this->status = STATUS_OPEN;
VerifyCertificate();
@@ -561,7 +554,7 @@ class mbedTLSIOHook : public SSLIOHook
return 1;
}
- this->status = ISSL_HANDSHAKING;
+ this->status = STATUS_HANDSHAKING;
if (ret == MBEDTLS_ERR_SSL_WANT_READ)
{
SocketEngine::ChangeEventMask(sock, FD_WANT_POLL_READ | FD_WANT_NO_WRITE);
@@ -581,9 +574,9 @@ class mbedTLSIOHook : public SSLIOHook
// Returns 1 if application I/O should proceed, 0 if it must wait for the underlying protocol to progress, -1 on fatal error
int PrepareIO(StreamSocket* sock)
{
- if (status == ISSL_HANDSHAKEN)
+ if (status == STATUS_OPEN)
return 1;
- else if (status == ISSL_HANDSHAKING)
+ else if (status == STATUS_HANDSHAKING)
{
// The handshake isn't finished, try to finish it
return Handshake(sock);
@@ -685,7 +678,6 @@ class mbedTLSIOHook : public SSLIOHook
public:
mbedTLSIOHook(std::shared_ptr<IOHookProvider> hookprov, StreamSocket* sock, bool isserver)
: SSLIOHook(hookprov)
- , status(ISSL_NONE)
{
mbedtls_ssl_init(&sess);
if (isserver)
@@ -711,7 +703,7 @@ class mbedTLSIOHook : public SSLIOHook
if (prepret <= 0)
return prepret;
- // If we resumed the handshake then this->status will be ISSL_HANDSHAKEN.
+ // If we resumed the handshake then this->status will be STATUS_OPEN.
char* const readbuf = ServerInstance->GetReadBuffer();
const size_t readbufsize = ServerInstance->Config->NetBufferSize;
int ret = mbedtls_ssl_read(&sess, reinterpret_cast<unsigned char*>(readbuf), readbufsize);
@@ -802,7 +794,7 @@ class mbedTLSIOHook : public SSLIOHook
void GetCiphersuite(std::string& out) const override
{
- if (!IsHandshakeDone())
+ if (!IsHookReady())
return;
out.append(mbedtls_ssl_get_version(&sess)).push_back('-');
@@ -822,7 +814,6 @@ class mbedTLSIOHook : public SSLIOHook
}
mbedTLS::Profile& GetProfile();
- bool IsHandshakeDone() const { return (status == ISSL_HANDSHAKEN); }
};
class mbedTLSIOHookProvider : public SSLIOHookProvider
@@ -952,7 +943,7 @@ class ModuleSSLmbedTLS : public Module
}
catch (ModuleException& ex)
{
- ServerInstance->Logs.Log(MODNAME, LOG_DEFAULT, ex.GetReason() + " Not applying settings.");
+ ServerInstance->SNO.WriteToSnoMask('a', "Failed to reload the mbedTLS TLS profiles. " + ex.GetReason());
}
}
@@ -973,7 +964,7 @@ class ModuleSSLmbedTLS : public Module
ModResult OnCheckReady(LocalUser* user) override
{
const mbedTLSIOHook* const iohook = static_cast<mbedTLSIOHook*>(user->eh.GetModHook(this));
- if ((iohook) && (!iohook->IsHandshakeDone()))
+ if ((iohook) && (!iohook->IsHookReady()))
return MOD_RES_DENY;
return MOD_RES_PASSTHRU;
}
diff --git a/src/modules/extra/m_ssl_openssl.cpp b/src/modules/extra/m_ssl_openssl.cpp
index 75adbd4e3..480a45ce1 100644
--- a/src/modules/extra/m_ssl_openssl.cpp
+++ b/src/modules/extra/m_ssl_openssl.cpp
@@ -52,8 +52,6 @@
# pragma comment(lib, "libeay32.lib")
#endif
-enum issl_status { ISSL_NONE, ISSL_HANDSHAKING, ISSL_OPEN };
-
static bool SelfSigned = false;
static int exdataindex;
@@ -501,7 +499,6 @@ class OpenSSLIOHook : public SSLIOHook
{
private:
SSL* sess;
- issl_status status;
bool data_to_write = false;
// Returns 1 if handshake succeeded, 0 if it is still in progress, -1 if it failed
@@ -516,13 +513,13 @@ class OpenSSLIOHook : public SSLIOHook
if (err == SSL_ERROR_WANT_READ)
{
SocketEngine::ChangeEventMask(user, FD_WANT_POLL_READ | FD_WANT_NO_WRITE);
- this->status = ISSL_HANDSHAKING;
+ this->status = STATUS_HANDSHAKING;
return 0;
}
else if (err == SSL_ERROR_WANT_WRITE)
{
SocketEngine::ChangeEventMask(user, FD_WANT_NO_READ | FD_WANT_SINGLE_WRITE);
- this->status = ISSL_HANDSHAKING;
+ this->status = STATUS_HANDSHAKING;
return 0;
}
else
@@ -536,7 +533,7 @@ class OpenSSLIOHook : public SSLIOHook
// Handshake complete.
VerifyCertificate();
- status = ISSL_OPEN;
+ status = STATUS_OPEN;
SocketEngine::ChangeEventMask(user, FD_WANT_POLL_READ | FD_WANT_NO_WRITE | FD_ADD_TRIAL_WRITE);
@@ -558,7 +555,7 @@ class OpenSSLIOHook : public SSLIOHook
}
sess = NULL;
certificate = NULL;
- status = ISSL_NONE;
+ status = STATUS_NONE;
}
void VerifyCertificate()
@@ -621,14 +618,14 @@ class OpenSSLIOHook : public SSLIOHook
void SSLInfoCallback(int where, int rc)
{
- if ((where & SSL_CB_HANDSHAKE_START) && (status == ISSL_OPEN))
+ if ((where & SSL_CB_HANDSHAKE_START) && (status == STATUS_OPEN))
{
if (GetProfile().AllowRenegotiation())
return;
// The other side is trying to renegotiate, kill the connection and change status
- // to ISSL_NONE so CheckRenego() closes the session
- status = ISSL_NONE;
+ // to STATUS_NONE so CheckRenego() closes the session
+ status = STATUS_NONE;
BIO* bio = SSL_get_rbio(sess);
EventHandler* eh = static_cast<StreamSocket*>(BIO_get_data(bio));
SocketEngine::Shutdown(eh, 2);
@@ -637,7 +634,7 @@ class OpenSSLIOHook : public SSLIOHook
bool CheckRenego(StreamSocket* sock)
{
- if (status != ISSL_NONE)
+ if (status != STATUS_NONE)
return true;
ServerInstance->Logs.Log(MODNAME, LOG_DEBUG, "Session %p killed, attempted to renegotiate", (void*)sess);
@@ -649,9 +646,9 @@ class OpenSSLIOHook : public SSLIOHook
// Returns 1 if application I/O should proceed, 0 if it must wait for the underlying protocol to progress, -1 on fatal error
int PrepareIO(StreamSocket* sock)
{
- if (status == ISSL_OPEN)
+ if (status == STATUS_OPEN)
return 1;
- else if (status == ISSL_HANDSHAKING)
+ else if (status == STATUS_HANDSHAKING)
{
// The handshake isn't finished, try to finish it
return Handshake(sock);
@@ -668,7 +665,7 @@ class OpenSSLIOHook : public SSLIOHook
OpenSSLIOHook(std::shared_ptr<IOHookProvider> hookprov, StreamSocket* sock, SSL* session)
: SSLIOHook(hookprov)
, sess(session)
- , status(ISSL_NONE)
+ , data_to_write(false)
{
// Create BIO instance and store a pointer to the socket in it which will be used by the read and write functions
BIO* bio = BIO_new(biomethods);
@@ -692,7 +689,7 @@ class OpenSSLIOHook : public SSLIOHook
if (prepret <= 0)
return prepret;
- // If we resumed the handshake then this->status will be ISSL_OPEN
+ // If we resumed the handshake then this->status will be STATUS_OPEN
{
ERR_clear_error();
char* buffer = ServerInstance->GetReadBuffer();
@@ -811,7 +808,7 @@ class OpenSSLIOHook : public SSLIOHook
void GetCiphersuite(std::string& out) const override
{
- if (!IsHandshakeDone())
+ if (!IsHookReady())
return;
out.append(SSL_get_version(sess)).push_back('-');
out.append(SSL_get_cipher(sess));
@@ -827,7 +824,6 @@ class OpenSSLIOHook : public SSLIOHook
return true;
}
- bool IsHandshakeDone() const { return (status == ISSL_OPEN); }
OpenSSL::Profile& GetProfile();
};
@@ -1009,7 +1005,7 @@ class ModuleSSLOpenSSL : public Module
}
catch (ModuleException& ex)
{
- ServerInstance->Logs.Log(MODNAME, LOG_DEFAULT, ex.GetReason() + " Not applying settings.");
+ ServerInstance->SNO.WriteToSnoMask('a', "Failed to reload the OpenSSL TLS (SSL) profiles. " + ex.GetReason());
}
}
@@ -1031,7 +1027,7 @@ class ModuleSSLOpenSSL : public Module
ModResult OnCheckReady(LocalUser* user) override
{
const OpenSSLIOHook* const iohook = static_cast<OpenSSLIOHook*>(user->eh.GetModHook(this));
- if ((iohook) && (!iohook->IsHandshakeDone()))
+ if ((iohook) && (!iohook->IsHookReady()))
return MOD_RES_DENY;
return MOD_RES_PASSTHRU;
}
diff --git a/src/modules/m_haproxy.cpp b/src/modules/m_haproxy.cpp
index b300a15d6..68c99eee1 100644
--- a/src/modules/m_haproxy.cpp
+++ b/src/modules/m_haproxy.cpp
@@ -384,6 +384,11 @@ class HAProxyHook : public IOHookMiddle
sock->AddIOHook(this);
}
+ bool IsHookReady() const override
+ {
+ return state == HPS_CONNECTED;
+ }
+
ssize_t OnStreamSocketWrite(StreamSocket* sock, StreamSocket::SendQueue& uppersendq) override
{
// We don't need to implement this.
diff --git a/src/modules/m_repeat.cpp b/src/modules/m_repeat.cpp
index af53fb6c2..2b1a82eec 100644
--- a/src/modules/m_repeat.cpp
+++ b/src/modules/m_repeat.cpp
@@ -388,6 +388,9 @@ class RepeatModule : public Module
if (res == MOD_RES_ALLOW)
return MOD_RES_PASSTHRU;
+ if (user->HasPrivPermission("channels/ignore-repeat"))
+ return MOD_RES_PASSTHRU;
+
if (rm.MatchLine(memb, settings, details.text))
{
if (settings->Action == ChannelSettings::ACT_BLOCK)
diff --git a/src/modules/m_websocket.cpp b/src/modules/m_websocket.cpp
index 6cf721424..242ecc372 100644
--- a/src/modules/m_websocket.cpp
+++ b/src/modules/m_websocket.cpp
@@ -35,17 +35,29 @@ static dynamic_reference_nocheck<HashProvider>* sha1;
struct WebSocketConfig
{
+ enum DefaultMode
+ {
+ // Reject connections if a subprotocol is not requested.
+ DM_REJECT,
+
+ // Use binary frames if a subprotocol is not requested.
+ DM_BINARY,
+
+ // Use UTF-8 text frames if a subprotocol is not requested.
+ DM_TEXT
+ };
+
typedef std::vector<std::string> OriginList;
typedef std::vector<std::string> ProxyRanges;
// The HTTP origins that can connect to the server.
OriginList allowedorigins;
+ // The method to use if a subprotocol is not negotiated.
+ DefaultMode defaultmode;
+
// The IP ranges which send trustworthy X-Real-IP or X-Forwarded-For headers.
ProxyRanges proxyranges;
-
- // Whether to send as UTF-8 text instead of binary data.
- bool sendastext;
};
class WebSocketHookProvider : public IOHookProvider
@@ -406,8 +418,10 @@ class WebSocketHook : public IOHookMiddle
irc::spacesepstream protostream(protocolheader.ExtractValue(recvq));
for (std::string proto; protostream.GetToken(proto); )
{
+ bool is_binary = stdalgo::string::equalsci(proto, "binary.inspircd.org");
bool is_text = stdalgo::string::equalsci(proto, "text.inspircd.org");
- if (stdalgo::string::equalsci(proto, "binary.inspircd.org") || is_text)
+
+ if (is_binary || is_text)
{
selectedproto = proto;
sendastext = is_text;
@@ -416,6 +430,12 @@ class WebSocketHook : public IOHookMiddle
}
}
+ if (selectedproto.empty() && config.defaultmode == WebSocketConfig::DM_REJECT)
+ {
+ FailHandshake(sock, "HTTP/1.1 400 Bad Request\r\nConnection: close\r\n\r\n", "WebSocket: Received HTTP request that did not send the Sec-WebSocket-Protocol header");
+ return -1;
+ }
+
HTTPHeaderFinder keyheader;
if (!keyheader.Find(recvq, "Sec-WebSocket-Key:", 18, reqend))
{
@@ -452,11 +472,16 @@ class WebSocketHook : public IOHookMiddle
WebSocketHook(std::shared_ptr<IOHookProvider> Prov, StreamSocket* sock, WebSocketConfig& cfg)
: IOHookMiddle(Prov)
, config(cfg)
- , sendastext(cfg.sendastext)
+ , sendastext(config.defaultmode != WebSocketConfig::DM_BINARY)
{
sock->AddIOHook(this);
}
+ bool IsHookReady() const override
+ {
+ return state == STATE_ESTABLISHED;
+ }
+
ssize_t OnStreamSocketWrite(StreamSocket* sock, StreamSocket::SendQueue& uppersendq) override
{
StreamSocket::SendQueue& mysendq = GetSendQ();
@@ -570,7 +595,16 @@ class ModuleWebSocket : public Module
}
auto tag = ServerInstance->Config->ConfValue("websocket");
- config.sendastext = tag->getBool("sendastext", true);
+
+ const std::string defaultmodestr = tag->getString("defaultmode", tag->getBool("sendastext", true) ? "text" : "binary", 1);
+ if (stdalgo::string::equalsci(defaultmodestr, "reject"))
+ config.defaultmode = WebSocketConfig::DM_REJECT;
+ else if (stdalgo::string::equalsci(defaultmodestr, "binary"))
+ config.defaultmode = WebSocketConfig::DM_BINARY;
+ else if (stdalgo::string::equalsci(defaultmodestr, "text"))
+ config.defaultmode = WebSocketConfig::DM_TEXT;
+ else
+ throw ModuleException(defaultmodestr + " is an invalid value for <websocket:defaultmode>; acceptable values are 'binary', 'text' and 'reject', at " + tag->source.str());
irc::spacesepstream proxyranges(tag->getString("proxyranges"));
for (std::string proxyrange; proxyranges.GetToken(proxyrange); )