diff --git a/bin/config_sample/config.ini b/bin/config_sample/config.ini index bd43618..a91a476 100644 --- a/bin/config_sample/config.ini +++ b/bin/config_sample/config.ini @@ -18,6 +18,7 @@ logbuffer=500 logging=modcall maximum_statements=10 multiclient_limit=15 +maximum_characters=256 [Dice] max_value=100 diff --git a/include/aoclient.h b/include/aoclient.h index 71ddf6f..1c2f799 100644 --- a/include/aoclient.h +++ b/include/aoclient.h @@ -2049,6 +2049,11 @@ class AOClient : public QObject { * @param incoming_message QString to be decoded. */ QString decodeMessage(QString incoming_message); + + /** + * @brief The size, in bytes, of the last data the client sent to the server. + */ + int last_read; }; #endif // AOCLIENT_H diff --git a/include/server.h b/include/server.h index f96fd79..230ffaf 100644 --- a/include/server.h +++ b/include/server.h @@ -286,6 +286,11 @@ class Server : public QObject { */ int multiclient_limit; + /** + * @brief Integer representing the maximum amount of characters an IC or OOC message can contain. + */ + int max_chars; + public slots: /** * @brief Handles a new connection. diff --git a/src/aoclient.cpp b/src/aoclient.cpp index 5ccfdf6..1fc9c92 100644 --- a/src/aoclient.cpp +++ b/src/aoclient.cpp @@ -19,7 +19,12 @@ void AOClient::clientData() { + if (last_read + socket->bytesAvailable() > 30720) { // Client can send a max of 30KB to the server over two sequential reads + socket->close(); + } + QString data = QString::fromUtf8(socket->readAll()); + last_read = data.size(); if (is_partial) { data = partial_packet + data; @@ -73,6 +78,10 @@ void AOClient::handlePacket(AOPacket packet) AreaData* area = server->areas[current_area]; PacketInfo info = packets.value(packet.header, {false, 0, &AOClient::pktDefault}); + if (packet.contents.join("").size() > 16384) { + return; + } + if (!checkAuth(info.acl_mask)) { return; } diff --git a/src/area_data.cpp b/src/area_data.cpp index 8289dc3..1e5f224 100644 --- a/src/area_data.cpp +++ b/src/area_data.cpp @@ -41,6 +41,7 @@ AreaData::AreaData(QString p_name, int p_index) : blankposting_allowed = areas_ini.value("blankposting_allowed","true").toBool(); force_immediate = areas_ini.value("force_immediate", "false").toBool(); toggle_music = areas_ini.value("toggle_music", "true").toBool(); + showname_allowed = areas_ini.value("shownames_allowed", "true").toBool(); areas_ini.endGroup(); QSettings config_ini("config/config.ini", QSettings::IniFormat); config_ini.beginGroup("Options"); diff --git a/src/packets.cpp b/src/packets.cpp index 98e25af..9c9459c 100644 --- a/src/packets.cpp +++ b/src/packets.cpp @@ -180,9 +180,14 @@ void AOClient::pktOocChat(AreaData* area, int argc, QStringList argv, AOPacket p ooc_name = dezalgo(argv[0]).replace(QRegExp("\\[|\\]|\\{|\\}|\\#|\\$|\\%|\\&"), ""); // no fucky wucky shit here if (ooc_name.isEmpty() || ooc_name == server->server_name) // impersonation & empty name protection return; + + if (ooc_name.length() > 30) { + sendServerMessage("Your name is too long! Please limit it to under 30 characters."); + return; + } QString message = dezalgo(argv[1]); - if (message.length() == 0) + if (message.length() == 0 || message.length() > server->max_chars) return; AOPacket final_packet("CT", {ooc_name, message, "0"}); if(message.at(0) == '/') { @@ -456,7 +461,6 @@ AOPacket AOClient::validateIcPacket(AOPacket packet) // and outgoing packets are different. Just RTFM. AOPacket invalid("INVALID", {}); - QStringList args; if (current_char == "" || !joined) // Spectators cannot use IC @@ -501,6 +505,9 @@ AOPacket AOClient::validateIcPacket(AOPacket packet) args.append(emote); // message text + if (incoming_args[4].toString().size() > server->max_chars) + return invalid; + QString incoming_msg = dezalgo(incoming_args[4].toString().trimmed()); if (!area->last_ic_message.isEmpty() && incoming_msg == area->last_ic_message[4] @@ -607,6 +614,15 @@ AOPacket AOClient::validateIcPacket(AOPacket packet) if (incoming_args.length() > 15) { // showname QString incoming_showname = dezalgo(incoming_args[15].toString().trimmed()); + if (!(incoming_showname == current_char || incoming_showname.isEmpty()) && !area->showname_allowed) { + sendServerMessage("Shownames are not allowed in this area!"); + return invalid; + } + if (incoming_showname.length() > 30) { + sendServerMessage("Your showname is too long! Please limit it to under 30 characters"); + return invalid; + } + // if the raw input is not empty but the trimmed input is, use a single space if (incoming_showname.isEmpty() && !incoming_args[15].toString().isEmpty()) incoming_showname = " "; diff --git a/src/server.cpp b/src/server.cpp index 30dea51..727a71b 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -283,6 +283,10 @@ void Server::loadServerConfig() multiclient_limit = config.value("multiclient_limit", "15").toInt(&multiclient_limit_conversion_success); if (!multiclient_limit_conversion_success) multiclient_limit = 15; + bool max_char_conversion_success; + max_chars = config.value("maximum_characters", "256").toInt(&max_char_conversion_success); + if (!max_char_conversion_success) + max_chars = 256; config.endGroup(); //Load dice values