Require always registering remote events for reception. Implement a fixed blacklist of remote events that can not be registered (see Network.cpp). Removed obsolete E_WINDOWMESSAGE event definition.

This commit is contained in:
Lasse Öörni 2014-09-29 14:08:32 +03:00
Родитель ea5a4bbf2a
Коммит cb0103d518
8 изменённых файлов: 67 добавлений и 16 удалений

Просмотреть файл

@ -164,6 +164,8 @@ function SubscribeToEvents()
SubscribeToEvent("ClientDisconnected", "HandleClientDisconnected")
-- This is a custom event, sent from the server to the client. It tells the node ID of the object the client should control
SubscribeToEvent("ClientObjectID", "HandleClientObjectID")
-- Events sent between client & server (remote events) must be explicitly registered or else they are not allowed to be received
network:RegisterRemoteEvent("ClientObjectID");
end
function CreateButton(text, width)

Просмотреть файл

@ -178,6 +178,8 @@ void SubscribeToEvents()
SubscribeToEvent("ClientDisconnected", "HandleClientDisconnected");
// This is a custom event, sent from the server to the client. It tells the node ID of the object the client should control
SubscribeToEvent("ClientObjectID", "HandleClientObjectID");
// Events sent between client & server (remote events) must be explicitly registered or else they are not allowed to be received
network.RegisterRemoteEvent("ClientObjectID");
}
Button@ CreateButton(const String& text, int width)

Просмотреть файл

@ -170,6 +170,7 @@ void InitScene()
void InitNetworking()
{
network.updateFps = 25; // 1/4 of physics FPS
// Remote events sent between client & server must be explicitly registered or else they are not allowed to be received
network.RegisterRemoteEvent("PlayerSpawned");
network.RegisterRemoteEvent("UpdateScore");
network.RegisterRemoteEvent("UpdateHiscores");

Просмотреть файл

@ -2071,9 +2071,9 @@ A remote event consists of its event type (name hash), a flag that tells whether
To send a remote event to a Connection, use its \ref Connection::SendRemoteEvent "SendRemoteEvent()" function. To broadcast remote events to several connections at once (server only), use Network's \ref Network::BroadcastRemoteEvent "BroadcastRemoteEvent()" function.
For safety, allowed remote event types should be registered so that a client can not for example trigger an internal render update event on the server. See \ref Network::RegisterRemoteEvent "RegisterRemoteEvent()". Similarly to file paths, as long as no remote event types are registered, all are allowed. The registration affects only receiving events; sending whatever event is always allowed.
For safety, allowed remote event types must be registered. See \ref Network::RegisterRemoteEvent "RegisterRemoteEvent()". The registration affects only receiving events; sending whatever event is always allowed. There is a fixed blacklist of event types defined in Source/Engine/Network/Network.cpp that pose a security risk and are never allowed to be registered for reception; for example E_CONSOLECOMMAND.
Like with ordinary events, in script event types are strings instead of name hashes for convenience.
Like with ordinary events, in script remote event types are strings instead of name hashes for convenience.
Remote events will always have the originating connection as a parameter in the event data. Here is how to get it in both C++ and script (in C++, include NetworkEvents.h):

Просмотреть файл

@ -27,16 +27,6 @@
namespace Urho3D
{
/// Operating system window message.
EVENT(E_WINDOWMESSAGE, WindowMessage)
{
PARAM(P_WINDOW, Window); // int
PARAM(P_MSG, Msg); // int
PARAM(P_WPARAM, WParam); // int
PARAM(P_LPARAM, LParam); // int
PARAM(P_HANDLED, Handled); // bool
}
/// New screen mode set.
EVENT(E_SCREENMODE, ScreenMode)
{

Просмотреть файл

@ -23,8 +23,11 @@
#include "Precompiled.h"
#include "Context.h"
#include "CoreEvents.h"
#include "EngineEvents.h"
#include "FileSystem.h"
#include "HttpRequest.h"
#include "InputEvents.h"
#include "IOEvents.h"
#include "Log.h"
#include "MemoryBuffer.h"
#include "Network.h"
@ -56,6 +59,49 @@ Network::Network(Context* context) :
SubscribeToEvent(E_BEGINFRAME, HANDLER(Network, HandleBeginFrame));
SubscribeToEvent(E_RENDERUPDATE, HANDLER(Network, HandleRenderUpdate));
// Blacklist remote events which are not to be allowed to be registered in any case
blacklistedRemoteEvents_.Insert(E_CONSOLECOMMAND);
blacklistedRemoteEvents_.Insert(E_LOGMESSAGE);
blacklistedRemoteEvents_.Insert(E_BEGINFRAME);
blacklistedRemoteEvents_.Insert(E_UPDATE);
blacklistedRemoteEvents_.Insert(E_POSTUPDATE);
blacklistedRemoteEvents_.Insert(E_RENDERUPDATE);
blacklistedRemoteEvents_.Insert(E_ENDFRAME);
blacklistedRemoteEvents_.Insert(E_MOUSEBUTTONDOWN);
blacklistedRemoteEvents_.Insert(E_MOUSEBUTTONUP);
blacklistedRemoteEvents_.Insert(E_MOUSEMOVE);
blacklistedRemoteEvents_.Insert(E_MOUSEWHEEL);
blacklistedRemoteEvents_.Insert(E_KEYDOWN);
blacklistedRemoteEvents_.Insert(E_KEYUP);
blacklistedRemoteEvents_.Insert(E_TEXTINPUT);
blacklistedRemoteEvents_.Insert(E_JOYSTICKCONNECTED);
blacklistedRemoteEvents_.Insert(E_JOYSTICKDISCONNECTED);
blacklistedRemoteEvents_.Insert(E_JOYSTICKBUTTONDOWN);
blacklistedRemoteEvents_.Insert(E_JOYSTICKBUTTONUP);
blacklistedRemoteEvents_.Insert(E_JOYSTICKAXISMOVE);
blacklistedRemoteEvents_.Insert(E_JOYSTICKHATMOVE);
blacklistedRemoteEvents_.Insert(E_TOUCHBEGIN);
blacklistedRemoteEvents_.Insert(E_TOUCHEND);
blacklistedRemoteEvents_.Insert(E_TOUCHMOVE);
blacklistedRemoteEvents_.Insert(E_GESTURERECORDED);
blacklistedRemoteEvents_.Insert(E_GESTUREINPUT);
blacklistedRemoteEvents_.Insert(E_MULTIGESTURE);
blacklistedRemoteEvents_.Insert(E_DROPFILE);
blacklistedRemoteEvents_.Insert(E_INPUTFOCUS);
blacklistedRemoteEvents_.Insert(E_MOUSEVISIBLECHANGED);
blacklistedRemoteEvents_.Insert(E_EXITREQUESTED);
blacklistedRemoteEvents_.Insert(E_SERVERCONNECTED);
blacklistedRemoteEvents_.Insert(E_SERVERDISCONNECTED);
blacklistedRemoteEvents_.Insert(E_CONNECTFAILED);
blacklistedRemoteEvents_.Insert(E_CLIENTCONNECTED);
blacklistedRemoteEvents_.Insert(E_CLIENTDISCONNECTED);
blacklistedRemoteEvents_.Insert(E_CLIENTIDENTITY);
blacklistedRemoteEvents_.Insert(E_CLIENTSCENELOADED);
blacklistedRemoteEvents_.Insert(E_NETWORKMESSAGE);
blacklistedRemoteEvents_.Insert(E_NETWORKUPDATE);
blacklistedRemoteEvents_.Insert(E_NETWORKUPDATESENT);
blacklistedRemoteEvents_.Insert(E_NETWORKSCENELOADFAILED);
}
Network::~Network()
@ -291,6 +337,12 @@ void Network::SetUpdateFps(int fps)
void Network::RegisterRemoteEvent(StringHash eventType)
{
if (blacklistedRemoteEvents_.Find(eventType) != blacklistedRemoteEvents_.End())
{
LOGERROR("Attempted to register blacklisted remote event type " + String(eventType));
return;
}
allowedRemoteEvents_.Insert(eventType);
}
@ -354,7 +406,7 @@ bool Network::IsServerRunning() const
bool Network::CheckRemoteEvent(StringHash eventType) const
{
return allowedRemoteEvents_.Empty() || allowedRemoteEvents_.Contains(eventType);
return allowedRemoteEvents_.Contains(eventType);
}
void Network::Update(float timeStep)

Просмотреть файл

@ -83,11 +83,11 @@ public:
void BroadcastRemoteEvent(Node* node, StringHash eventType, bool inOrder, const VariantMap& eventData = Variant::emptyVariantMap);
/// Set network update FPS.
void SetUpdateFps(int fps);
/// Register a remote event as allowed to be sent and received. If no events are registered, all are allowed.
/// Register a remote event as allowed to be received. There is also a fixed blacklist of events that can not be allowed in any case, such as ConsoleCommand.
void RegisterRemoteEvent(StringHash eventType);
/// Unregister a remote event as allowed to be sent and received.
/// Unregister a remote event as allowed to received.
void UnregisterRemoteEvent(StringHash eventType);
/// Unregister all remote events. This results in all being allowed.
/// Unregister all remote events.
void UnregisterAllRemoteEvents();
/// Set the package download cache directory.
void SetPackageCacheDir(const String& path);
@ -132,6 +132,8 @@ private:
HashMap<kNet::MessageConnection*, SharedPtr<Connection> > clientConnections_;
/// Allowed remote events.
HashSet<StringHash> allowedRemoteEvents_;
/// Remote event fixed blacklist.
HashSet<StringHash> blacklistedRemoteEvents_;
/// Networked scenes.
HashSet<Scene*> networkScenes_;
/// Update FPS.

Просмотреть файл

@ -233,6 +233,8 @@ void SceneReplication::SubscribeToEvents()
SubscribeToEvent(E_CLIENTDISCONNECTED, HANDLER(SceneReplication, HandleClientDisconnected));
// This is a custom event, sent from the server to the client. It tells the node ID of the object the client should control
SubscribeToEvent(E_CLIENTOBJECTID, HANDLER(SceneReplication, HandleClientObjectID));
// Events sent between client & server (remote events) must be explicitly registered or else they are not allowed to be received
GetSubsystem<Network>()->RegisterRemoteEvent(E_CLIENTOBJECTID);
}
Button* SceneReplication::CreateButton(const String& text, int width)