From 9c9f30790e6d3495f65933947f1c067a55fc48e4 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Fri, 9 Dec 2016 22:38:11 +1100 Subject: [PATCH] Added character validation --- client/scenes/world.cpp | 2 +- common/utilities/file_hash.cpp | 60 ++++++++++++++++++++++++++++++++++ common/utilities/file_hash.hpp | 26 +++++++++++++++ server/server_application.cpp | 37 ++++++++++++++++++++- 4 files changed, 123 insertions(+), 2 deletions(-) create mode 100644 common/utilities/file_hash.cpp create mode 100644 common/utilities/file_hash.hpp diff --git a/client/scenes/world.cpp b/client/scenes/world.cpp index 102fd3a..02682ea 100644 --- a/client/scenes/world.cpp +++ b/client/scenes/world.cpp @@ -154,7 +154,7 @@ void World::Update() { throw(e); } catch(std::exception& e) { - std::cerr << "HandlePacket Error: " << e.what() << std::endl; + std::cerr << "HandlePacket Error (" << (int)(reinterpret_cast(packetBuffer)->type) << "): " << e.what() << std::endl; } //free the buffer diff --git a/common/utilities/file_hash.cpp b/common/utilities/file_hash.cpp new file mode 100644 index 0000000..c3fb203 --- /dev/null +++ b/common/utilities/file_hash.cpp @@ -0,0 +1,60 @@ +/* Copyright: (c) Kayne Ruse 2016 + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. +*/ +#include "file_hash.hpp" + +#include + +//hash a byte array into a 32-bit integer +unsigned fnv_hash_1a_32(void *key, int len) { + unsigned char *p = static_cast(key); + unsigned h = 0x811c9dc5; + for (int i = 0; i < len; i++) { + h = ( h ^ p[i] ) * 0x01000193; + } + return h; +} + +int getFileHash(std::string fname) { + std::ifstream is(fname, std::ios::in | std::ios::binary); + + //if the file doesn't exist, return a hash of -1 + if (!is.is_open()) { + return -1; + } + + //get the file size + is.seekg(0, std::ios_base::end); + int size = is.tellg(); + is.seekg(0); + + //create a buffer of that size + char buffer[size]; + + //load the data + is.read(buffer, size); + + //cleanup + is.close(); + + //finally, return the hash value + return fnv_hash_1a_32(buffer, size); +} diff --git a/common/utilities/file_hash.hpp b/common/utilities/file_hash.hpp new file mode 100644 index 0000000..06fa4db --- /dev/null +++ b/common/utilities/file_hash.hpp @@ -0,0 +1,26 @@ +/* Copyright: (c) Kayne Ruse 2016 + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. +*/ +#pragma once + +#include + +int getFileHash(std::string fname); \ No newline at end of file diff --git a/server/server_application.cpp b/server/server_application.cpp index 567393e..11d6e01 100644 --- a/server/server_application.cpp +++ b/server/server_application.cpp @@ -22,6 +22,7 @@ #include "server_application.hpp" //utility functions +#include "file_hash.hpp" #include "sql_tools.hpp" //std & STL @@ -181,7 +182,7 @@ void ServerApplication::Proc() { HandlePacket(packetBuffer); } catch(std::exception& e) { - std::cerr << "HandlePacket Error: " << e.what() << std::endl; + std::cerr << "HandlePacket Error (" << (int)(packetBuffer->type) << "): " << e.what() << std::endl; } //reset the buffer memset(packetBuffer, 0, MAX_PACKET_SIZE); @@ -607,8 +608,25 @@ void ServerApplication::hQueryCharacterExists(CharacterPacket* const argPacket) } void ServerApplication::hCharacterCreate(CharacterPacket* const argPacket) { + //check to see of the character's files are valid + if (getFileHash(config["dir.sprites"] + argPacket->avatar) == -1) { + //build the error message + std::ostringstream msg; + msg << "Character avatar is invalid on this server: " << argPacket->avatar; + + //build & send the packet + TextPacket newPacket; + newPacket.type = SerialPacketType::CHARACTER_REJECTION; + strncpy(newPacket.text, msg.str().c_str(), PACKET_STRING_SIZE); + network.SendTo(argPacket->srcAddress, static_cast(&newPacket)); + + return; + } + + //create the character int characterIndex = characterMgr.Create(argPacket->accountIndex, argPacket->handle, argPacket->avatar); + //check to see of the character already exists if (characterIndex < 0) { //build the error message std::ostringstream msg; @@ -683,8 +701,25 @@ void ServerApplication::hCharacterDelete(CharacterPacket* const argPacket) { } void ServerApplication::hCharacterLoad(CharacterPacket* const argPacket) { + //check to see of the character's files are valid + if (getFileHash(config["dir.sprites"] + argPacket->avatar) == -1) { + //build the error message + std::ostringstream msg; + msg << "Character avatar is invalid on this server: " << argPacket->avatar; + + //build & send the packet + TextPacket newPacket; + newPacket.type = SerialPacketType::CHARACTER_REJECTION; + strncpy(newPacket.text, msg.str().c_str(), PACKET_STRING_SIZE); + network.SendTo(argPacket->srcAddress, static_cast(&newPacket)); + + return; + } + + //load the character int characterIndex = characterMgr.Load(argPacket->accountIndex, argPacket->handle, argPacket->avatar); + //check to see if the character is already loaded if (characterIndex < 0) { //build the error message std::ostringstream msg;