mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	network: check Console ID conflicts
As Console ID can be sensitive data sometimes, this implementation sent a SHA256 hash of it instead.
This commit is contained in:
		
							parent
							
								
									3c589f473f
								
							
						
					
					
						commit
						c396e3c6e5
					
				
					 14 changed files with 109 additions and 23 deletions
				
			
		|  | @ -31,10 +31,11 @@ public: | |||
|     std::string password; ///< The password required to connect to this room.
 | ||||
| 
 | ||||
|     struct Member { | ||||
|         std::string nickname;   ///< The nickname of the member.
 | ||||
|         GameInfo game_info;     ///< The current game of the member
 | ||||
|         MacAddress mac_address; ///< The assigned mac address of the member.
 | ||||
|         ENetPeer* peer;         ///< The remote peer.
 | ||||
|         std::string nickname;        ///< The nickname of the member.
 | ||||
|         std::string console_id_hash; ///< A hash of the console ID of the member.
 | ||||
|         GameInfo game_info;          ///< The current game of the member
 | ||||
|         MacAddress mac_address;      ///< The assigned mac address of the member.
 | ||||
|         ENetPeer* peer;              ///< The remote peer.
 | ||||
|     }; | ||||
|     using MemberList = std::vector<Member>; | ||||
|     MemberList members;              ///< Information about the members of this room
 | ||||
|  | @ -69,6 +70,12 @@ public: | |||
|      */ | ||||
|     bool IsValidMacAddress(const MacAddress& address) const; | ||||
| 
 | ||||
|     /**
 | ||||
|      * Returns whether the console ID (hash) is valid, ie. isn't already taken by someone else in | ||||
|      * the room. | ||||
|      */ | ||||
|     bool IsValidConsoleId(const std::string& console_id_hash) const; | ||||
| 
 | ||||
|     /**
 | ||||
|      * Sends a ID_ROOM_IS_FULL message telling the client that the room is full. | ||||
|      */ | ||||
|  | @ -84,6 +91,12 @@ public: | |||
|      */ | ||||
|     void SendMacCollision(ENetPeer* client); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Sends a IdConsoleIdCollison message telling the client that another member with the same | ||||
|      * console ID exists. | ||||
|      */ | ||||
|     void SendConsoleIdCollision(ENetPeer* client); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Sends a ID_ROOM_VERSION_MISMATCH message telling the client that the version is invalid. | ||||
|      */ | ||||
|  | @ -212,6 +225,9 @@ void Room::RoomImpl::HandleJoinRequest(const ENetEvent* event) { | |||
|     std::string nickname; | ||||
|     packet >> nickname; | ||||
| 
 | ||||
|     std::string console_id_hash; | ||||
|     packet >> console_id_hash; | ||||
| 
 | ||||
|     MacAddress preferred_mac; | ||||
|     packet >> preferred_mac; | ||||
| 
 | ||||
|  | @ -242,6 +258,11 @@ void Room::RoomImpl::HandleJoinRequest(const ENetEvent* event) { | |||
|         preferred_mac = GenerateMacAddress(); | ||||
|     } | ||||
| 
 | ||||
|     if (!IsValidConsoleId(console_id_hash)) { | ||||
|         SendConsoleIdCollision(event->peer); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     if (client_version != network_version) { | ||||
|         SendVersionMismatch(event->peer); | ||||
|         return; | ||||
|  | @ -250,6 +271,7 @@ void Room::RoomImpl::HandleJoinRequest(const ENetEvent* event) { | |||
|     // At this point the client is ready to be added to the room.
 | ||||
|     Member member{}; | ||||
|     member.mac_address = preferred_mac; | ||||
|     member.console_id_hash = console_id_hash; | ||||
|     member.nickname = nickname; | ||||
|     member.peer = event->peer; | ||||
| 
 | ||||
|  | @ -282,6 +304,14 @@ bool Room::RoomImpl::IsValidMacAddress(const MacAddress& address) const { | |||
|                        [&address](const auto& member) { return member.mac_address != address; }); | ||||
| } | ||||
| 
 | ||||
| bool Room::RoomImpl::IsValidConsoleId(const std::string& console_id_hash) const { | ||||
|     // A Console ID is valid if it is not already taken by anybody else in the room.
 | ||||
|     std::lock_guard<std::mutex> lock(member_mutex); | ||||
|     return std::all_of(members.begin(), members.end(), [&console_id_hash](const auto& member) { | ||||
|         return member.console_id_hash != console_id_hash; | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| void Room::RoomImpl::SendNameCollision(ENetPeer* client) { | ||||
|     Packet packet; | ||||
|     packet << static_cast<u8>(IdNameCollision); | ||||
|  | @ -302,6 +332,16 @@ void Room::RoomImpl::SendMacCollision(ENetPeer* client) { | |||
|     enet_host_flush(server); | ||||
| } | ||||
| 
 | ||||
| void Room::RoomImpl::SendConsoleIdCollision(ENetPeer* client) { | ||||
|     Packet packet; | ||||
|     packet << static_cast<u8>(IdConsoleIdCollision); | ||||
| 
 | ||||
|     ENetPacket* enet_packet = | ||||
|         enet_packet_create(packet.GetData(), packet.GetDataSize(), ENET_PACKET_FLAG_RELIABLE); | ||||
|     enet_peer_send(client, 0, enet_packet); | ||||
|     enet_host_flush(server); | ||||
| } | ||||
| 
 | ||||
| void Room::RoomImpl::SendWrongPassword(ENetPeer* client) { | ||||
|     Packet packet; | ||||
|     packet << static_cast<u8>(IdWrongPassword); | ||||
|  |  | |||
|  | @ -59,6 +59,7 @@ enum RoomMessageTypes : u8 { | |||
|     IdWrongPassword, | ||||
|     IdCloseRoom, | ||||
|     IdRoomIsFull, | ||||
|     IdConsoleIdCollision, | ||||
| }; | ||||
| 
 | ||||
| /// This is what a server [person creating a server] would use.
 | ||||
|  |  | |||
|  | @ -73,11 +73,12 @@ public: | |||
|      * Sends a request to the server, asking for permission to join a room with the specified | ||||
|      * nickname and preferred mac. | ||||
|      * @params nickname The desired nickname. | ||||
|      * @params console_id_hash A hash of the Console ID. | ||||
|      * @params preferred_mac The preferred MAC address to use in the room, the NoPreferredMac tells | ||||
|      * @params password The password for the room | ||||
|      * the server to assign one for us. | ||||
|      */ | ||||
|     void SendJoinRequest(const std::string& nickname, | ||||
|     void SendJoinRequest(const std::string& nickname, const std::string& console_id_hash, | ||||
|                          const MacAddress& preferred_mac = NoPreferredMac, | ||||
|                          const std::string& password = ""); | ||||
| 
 | ||||
|  | @ -163,6 +164,9 @@ void RoomMember::RoomMemberImpl::MemberLoop() { | |||
|                 case IdMacCollision: | ||||
|                     SetState(State::MacCollision); | ||||
|                     break; | ||||
|                 case IdConsoleIdCollision: | ||||
|                     SetState(State::ConsoleIdCollision); | ||||
|                     break; | ||||
|                 case IdVersionMismatch: | ||||
|                     SetState(State::WrongVersion); | ||||
|                     break; | ||||
|  | @ -204,11 +208,13 @@ void RoomMember::RoomMemberImpl::Send(Packet&& packet) { | |||
| } | ||||
| 
 | ||||
| void RoomMember::RoomMemberImpl::SendJoinRequest(const std::string& nickname, | ||||
|                                                  const std::string& console_id_hash, | ||||
|                                                  const MacAddress& preferred_mac, | ||||
|                                                  const std::string& password) { | ||||
|     Packet packet; | ||||
|     packet << static_cast<u8>(IdJoinRequest); | ||||
|     packet << nickname; | ||||
|     packet << console_id_hash; | ||||
|     packet << preferred_mac; | ||||
|     packet << network_version; | ||||
|     packet << password; | ||||
|  | @ -392,9 +398,9 @@ RoomInformation RoomMember::GetRoomInformation() const { | |||
|     return room_member_impl->room_information; | ||||
| } | ||||
| 
 | ||||
| void RoomMember::Join(const std::string& nick, const char* server_addr, u16 server_port, | ||||
|                       u16 client_port, const MacAddress& preferred_mac, | ||||
|                       const std::string& password) { | ||||
| void RoomMember::Join(const std::string& nick, const std::string& console_id_hash, | ||||
|                       const char* server_addr, u16 server_port, u16 client_port, | ||||
|                       const MacAddress& preferred_mac, const std::string& password) { | ||||
|     // If the member is connected, kill the connection first
 | ||||
|     if (room_member_impl->loop_thread && room_member_impl->loop_thread->joinable()) { | ||||
|         Leave(); | ||||
|  | @ -427,7 +433,7 @@ void RoomMember::Join(const std::string& nick, const char* server_addr, u16 serv | |||
|     if (net > 0 && event.type == ENET_EVENT_TYPE_CONNECT) { | ||||
|         room_member_impl->nickname = nick; | ||||
|         room_member_impl->StartLoop(); | ||||
|         room_member_impl->SendJoinRequest(nick, preferred_mac, password); | ||||
|         room_member_impl->SendJoinRequest(nick, console_id_hash, preferred_mac, password); | ||||
|         SendGameInfo(room_member_impl->current_game_info); | ||||
|     } else { | ||||
|         enet_peer_disconnect(room_member_impl->server, 0); | ||||
|  |  | |||
|  | @ -54,12 +54,13 @@ public: | |||
|         LostConnection, ///< Connection closed
 | ||||
| 
 | ||||
|         // Reasons why connection was rejected
 | ||||
|         NameCollision,   ///< Somebody is already using this name
 | ||||
|         MacCollision,    ///< Somebody is already using that mac-address
 | ||||
|         WrongVersion,    ///< The room version is not the same as for this RoomMember
 | ||||
|         WrongPassword,   ///< The password doesn't match the one from the Room
 | ||||
|         CouldNotConnect, ///< The room is not responding to a connection attempt
 | ||||
|         RoomIsFull       ///< Room is already at the maximum number of players
 | ||||
|         NameCollision,      ///< Somebody is already using this name
 | ||||
|         MacCollision,       ///< Somebody is already using that mac-address
 | ||||
|         ConsoleIdCollision, ///< Somebody in the room has the same Console ID
 | ||||
|         WrongVersion,       ///< The room version is not the same as for this RoomMember
 | ||||
|         WrongPassword,      ///< The password doesn't match the one from the Room
 | ||||
|         CouldNotConnect,    ///< The room is not responding to a connection attempt
 | ||||
|         RoomIsFull          ///< Room is already at the maximum number of players
 | ||||
|     }; | ||||
| 
 | ||||
|     struct MemberInformation { | ||||
|  | @ -116,11 +117,13 @@ public: | |||
| 
 | ||||
|     /**
 | ||||
|      * Attempts to join a room at the specified address and port, using the specified nickname. | ||||
|      * This may fail if the username is already taken. | ||||
|      * A console ID hash is passed in to check console ID conflicts. | ||||
|      * This may fail if the username or console ID is already taken. | ||||
|      */ | ||||
|     void Join(const std::string& nickname, const char* server_addr = "127.0.0.1", | ||||
|               const u16 server_port = DefaultRoomPort, const u16 client_port = 0, | ||||
|               const MacAddress& preferred_mac = NoPreferredMac, const std::string& password = ""); | ||||
|     void Join(const std::string& nickname, const std::string& console_id_hash, | ||||
|               const char* server_addr = "127.0.0.1", const u16 server_port = DefaultRoomPort, | ||||
|               const u16 client_port = 0, const MacAddress& preferred_mac = NoPreferredMac, | ||||
|               const std::string& password = ""); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Sends a WiFi packet to the room. | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue