diff --git a/Sources/Plasma/PubUtilLib/plNetClient/plNetClientMgr.h b/Sources/Plasma/PubUtilLib/plNetClient/plNetClientMgr.h index cb5b7743..6f73f4da 100644 --- a/Sources/Plasma/PubUtilLib/plNetClient/plNetClientMgr.h +++ b/Sources/Plasma/PubUtilLib/plNetClient/plNetClientMgr.h @@ -34,6 +34,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "plNetVoiceList.h" #include "plNetClientMsgHandler.h" #include "plNetClientStats.h" // STATS Counters +#include "plNetClientMsgScreener.h" #include "pnNetCommon/plNetApp.h" @@ -162,6 +163,7 @@ private: plNetTalkList fTalkList; // other players I'm talking to plNetClientMsgHandler fMsgHandler; + plNetClientMsgScreener fScreener; // recorder support plNetClientRecorder* fMsgRecorder; diff --git a/Sources/Plasma/PubUtilLib/plNetClient/plNetClientMgrSend.cpp b/Sources/Plasma/PubUtilLib/plNetClient/plNetClientMgrSend.cpp index e17f43bc..60768eb7 100644 --- a/Sources/Plasma/PubUtilLib/plNetClient/plNetClientMgrSend.cpp +++ b/Sources/Plasma/PubUtilLib/plNetClient/plNetClientMgrSend.cpp @@ -28,7 +28,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "plNetClientMgr.h" #include "plCreatableIndex.h" #include "plNetObjectDebugger.h" -#include "plNetClientMsgScreener.h" #include "pnNetCommon/plSynchedObject.h" #include "pnNetCommon/plSDLTypes.h" @@ -220,8 +219,7 @@ int plNetClientMgr::ISendGameMessage(plMessage* msg) if (GetFlagsBit(kDisabled)) return hsOK; - static plNetClientMsgScreener screener; // make static so that there's only 1 log per session - if (!screener.AllowMessage(msg)) + if (!fScreener.AllowOutgoingMessage(msg)) { if (GetFlagsBit(kScreenMessages)) return hsOK; // filter out illegal messages diff --git a/Sources/Plasma/PubUtilLib/plNetClient/plNetClientMsgHandler.cpp b/Sources/Plasma/PubUtilLib/plNetClient/plNetClientMsgHandler.cpp index 563e413e..111e63c9 100644 --- a/Sources/Plasma/PubUtilLib/plNetClient/plNetClientMsgHandler.cpp +++ b/Sources/Plasma/PubUtilLib/plNetClient/plNetClientMsgHandler.cpp @@ -351,6 +351,12 @@ MSG_HANDLER_DEFN(plNetClientMsgHandler,plNetMsgGameMessage) nc->DebugMsg("Converting game msg future timeStamp, curT=%f, futT=%f", secs, timeStamp); } + // Do some basic security checks on the incoming message because + // we cannot nesecarily trust the server because the server trusts + // the remote client WAY too much. + if (!IGetNetClientMgr()->fScreener.AllowIncomingMessage(gameMsg)) + return hsOK; + plgDispatch::Dispatch()->MsgSend(gameMsg); // Debug diff --git a/Sources/Plasma/PubUtilLib/plNetClient/plNetClientMsgScreener.cpp b/Sources/Plasma/PubUtilLib/plNetClient/plNetClientMsgScreener.cpp index 2d1bc820..324780cf 100644 --- a/Sources/Plasma/PubUtilLib/plNetClient/plNetClientMsgScreener.cpp +++ b/Sources/Plasma/PubUtilLib/plNetClient/plNetClientMsgScreener.cpp @@ -23,9 +23,11 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com Mead, WA 99021 *==LICENSE==*/ +#include "plCreatableIndex.h" #include "plNetClientMsgScreener.h" #include "plNetLinkingMgr.h" +#include "pfMessage/pfKIMsg.h" #include "pnNetCommon/plNetApp.h" #include "pnMessage/plMessage.h" @@ -86,7 +88,7 @@ bool plNetClientMsgScreener::IIsSenderCCR(const plNetGameMember* gm) const // // return true if msg is allowed/accepted as a net msg // -bool plNetClientMsgScreener::AllowMessage(const plMessage* msg) const +bool plNetClientMsgScreener::AllowOutgoingMessage(const plMessage* msg) const { if (!msg) return false; @@ -96,14 +98,60 @@ bool plNetClientMsgScreener::AllowMessage(const plMessage* msg) const return true; if (ans==kNo) { - // WarningMsg("Quick-reject net propagated msg %s", msg->ClassName()); + WarningMsg("Rejected: (Outgoing) %s [Illegal Message]", msg->ClassName()); return false; } if (!IValidateMessage(msg)) { - // WarningMsg("Validation failed. Blocking net propagated msg %s", msg->ClassName()); + WarningMsg("Rejected: (Outgoing) %s [Validation Failed]", msg->ClassName()); return false; } return true; } + +// +// Return false for obvious hacked network messages +// This is all because we cannot trust Cyan's servers +// +bool plNetClientMsgScreener::AllowIncomingMessage(const plMessage* msg) const +{ + if (!msg) + return false; + + bool result = IScreenIncoming(msg); + if (!result) + WarningMsg("Rejected: (Incoming) %s", msg->ClassName()); + + return result; +} + +bool plNetClientMsgScreener::IScreenIncoming(const plMessage* msg) const +{ + // Why would you EVER send a RefMsg accross the network??? + if (plFactory::DerivesFrom(CLASS_INDEX_SCOPED(plRefMsg), msg->ClassIndex())) + return false; + + // Blacklist some obvious hacks here... + switch (msg->ClassIndex()) + { + case CLASS_INDEX_SCOPED(plAudioSysMsg): + // This message has a flawed read/write + return false; + case CLASS_INDEX_SCOPED(plConsoleMsg): + // Python remote code execution vunerability + return false; + case CLASS_INDEX_SCOPED(pfKIMsg): + { + // Only accept Chat Messages! + const pfKIMsg* ki = pfKIMsg::ConvertNoRef(msg); + if (ki->GetCommand() != pfKIMsg::kHACKChatMsg) + return false; + return true; + } + default: + // Default allow everything else, otherweise we + // might break something that we really shouldn't... + return true; + } +} diff --git a/Sources/Plasma/PubUtilLib/plNetClient/plNetClientMsgScreener.h b/Sources/Plasma/PubUtilLib/plNetClient/plNetClientMsgScreener.h index 9313b03c..316f8a30 100644 --- a/Sources/Plasma/PubUtilLib/plNetClient/plNetClientMsgScreener.h +++ b/Sources/Plasma/PubUtilLib/plNetClient/plNetClientMsgScreener.h @@ -41,11 +41,13 @@ protected: bool IIsLocalArmatureModKey(plKey key, const plNetGameMember* gm) const; bool IIsSenderCCR(const plNetGameMember* gm=nil) const; bool IAmClient() const { return true; } + bool IScreenIncoming(const plMessage* msg) const; public: plNetClientMsgScreener(); - bool AllowMessage(const plMessage* msg) const; + bool AllowOutgoingMessage(const plMessage* msg) const; + bool AllowIncomingMessage(const plMessage* msg) const; };