浏览代码

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.

Lasse Öörni 11 年之前
父节点
当前提交
cb0103d518

+ 2 - 0
Bin/Data/LuaScripts/17_SceneReplication.lua

@@ -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)

+ 2 - 0
Bin/Data/Scripts/17_SceneReplication.as

@@ -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)

+ 1 - 0
Bin/Data/Scripts/NinjaSnowWar.as

@@ -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");

+ 2 - 2
Docs/Reference.dox

@@ -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):
 

+ 0 - 10
Source/Engine/Graphics/GraphicsEvents.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)
 {

+ 53 - 1
Source/Engine/Network/Network.cpp

@@ -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)

+ 5 - 3
Source/Engine/Network/Network.h

@@ -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.

+ 2 - 0
Source/Samples/17_SceneReplication/SceneReplication.cpp

@@ -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)