// Ryzom - MMORPG Framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . #include "stdpch.h" #include "permanent_ban.h" #include "nel/misc/file.h" #include "nel/misc/path.h" #include "nel/misc/big_file.h" #include "nel/misc/random.h" using namespace NLMISC; #define REGKEY_RYZOM_PATH L"Software\\Nevrax\\ryzom" #define REGKEY_PERMANENT_BAN L"PB" // ************************************************************ static void setPermanentBanRegistryKey(bool on) { #ifndef NL_OS_WINDOWS nlinfo("Not implemented"); #else HKEY hKey; if (RegCreateKeyW(HKEY_CURRENT_USER, REGKEY_RYZOM_PATH, &hKey)==ERROR_SUCCESS) { DWORD permanentBan = on ? 1 : 0; LONG result = RegSetValueExW(hKey, REGKEY_PERMANENT_BAN, 0, REG_DWORD, (LPBYTE)&permanentBan, 4); if (result != ERROR_SUCCESS) { nlwarning("pb key not created"); } } else { nlwarning("pb key not created"); } #endif } // ************************************************************ static bool getPermanentBanRegistryKey() { #ifndef NL_OS_WINDOWS return false; // not implemented #else HKEY hKey; if (RegOpenKeyExW(HKEY_CURRENT_USER, REGKEY_RYZOM_PATH, 0, KEY_READ, &hKey) == ERROR_SUCCESS) { DWORD permanentBan; DWORD type; DWORD dataSize = sizeof(DWORD); RegQueryValueExW(hKey, REGKEY_PERMANENT_BAN, 0, &type, (LPBYTE)&permanentBan, &dataSize); if (type == REG_DWORD && dataSize == sizeof(DWORD)) { return permanentBan != 0; } } return false; #endif } // *********************************************************** static void setPermanentBanFileMarker(const std::string &path, bool on) { if (on) { try { // simply touch a file COFile f(path); #ifdef NL_OS_WINDOWS SetFileAttributesW(utf8ToWide(path), FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM); #endif } catch(const EStream &e) { nlinfo(e.what()); } } else { CFile::deleteFile(path); } } // *********************************************************** static bool getPermanentBanFileMarker(const std::string &path) { return CFile::isExists(path); } #define PERMANENT_BAN_FILE0 "c:\\3289763c1ecd044e" #define PERMANENT_BAN_FILE1 "78d0732e50bf2bbd" // ************************************************************ void setPermanentBanMarkers(bool on) { setPermanentBanRegistryKey(on); setPermanentBanFileMarker(PERMANENT_BAN_FILE0, on); setPermanentBanFileMarker(CPath::getWindowsDirectory() + PERMANENT_BAN_FILE1, on); } // ************************************************************ bool testPermanentBanMarkers() { /*#ifndef NL_OS_WINDOWS nlinfo("Not implemented"); return false; #else if (getPermanentBanRegistryKey()) return true; if (getPermanentBanFileMarker(PERMANENT_BAN_FILE0)) return true; if (getPermanentBanFileMarker(CPath::getWindowsDirectory() + PERMANENT_BAN_FILE1)) return true; #endif return false; */ return false; } // mark a bnp file without corrupting its datas (this force the patch to be applied the next time the client is launched, thus delaying the trouble maker) static void markBNPFile(std::string &path) { CRandom rnd; rnd.srand((sint32) CTime::getLocalTime()); uint32 nFileSize=CFile::getFileSize(path); if (!nFileSize) return; FILE *f = nlfopen(path, "rb+"); if (!f) return; // Result if (nlfseek64 (f, nFileSize-4, SEEK_SET) != 0) { fclose (f); return; } uint32 nOffsetFromBeginning; if (fread (&nOffsetFromBeginning, sizeof(uint32), 1, f) != 1) { fclose (f); return; } #ifdef NL_BIG_ENDIAN NLMISC_BSWAP32(nOffsetFromBeginning); #endif if (nlfseek64 (f, nOffsetFromBeginning, SEEK_SET) != 0) { fclose (f); return; } // Read the file count uint32 nNbFile; if (fread (&nNbFile, sizeof(uint32), 1, f) != 1) { fclose (f); return; } #ifdef NL_BIG_ENDIAN NLMISC_BSWAP32(nNbFile); #endif for (uint32 i = 0; i < nNbFile; ++i) { char FileName[MAX_PATH]; uint8 nStringSize; if (fread (&nStringSize, 1, 1, f) != 1) { fclose(f); return; } sint64 currPos = nlftell64(f); if (currPos < 0) { fclose(f); return; } if (fread (FileName, 1, nStringSize, f) != nStringSize) { fclose (f); return; } FileName[nStringSize] = 0; for(uint k = 0; k < nStringSize; ++k) { if (rnd.rand() & 1) FileName[k] = toupper(FileName[k]); else FileName[k] = tolower(FileName[k]); } if (nlfseek64 (f, currPos, SEEK_SET) != 0) { fclose (f); return; } // write shuffled version if (fwrite(FileName, 1, nStringSize, f) != nStringSize) { fclose(f); return; } fflush(f); uint32 nFileSize2; if (fread (&nFileSize2, sizeof(uint32), 1, f) != 1) { fclose (f); return; } #ifdef NL_BIG_ENDIAN NLMISC_BSWAP32(nFileSize2); #endif uint32 nFilePos; if (fread (&nFilePos, sizeof(uint32), 1, f) != 1) { fclose (f); return; } #ifdef NL_BIG_ENDIAN NLMISC_BSWAP32(nFilePos); #endif } fclose (f); } // ************************************************************ void applyPermanentBanPunishment() { // go in the data directory & touch all bnp files so that the client should repatch all its datas std::vector bigFilePaths; CBigFile::getInstance().getBigFilePaths(bigFilePaths); for(uint k = 0; k < bigFilePaths.size(); ++k) { markBNPFile(bigFilePaths[k]); } }