void PHandler_Load(char* name) // Load a plugin, safe for use { int i,j; char* realpath; char filepathbuf[MAX_OSPATH]; char hash[128]; long unsigned sizeofhash; void *lib_handle; pluginInfo_t info; if(!pluginFunctions.enabled){ Com_Printf("Plugin handler is not initialized!\n"); return; } if(pluginFunctions.loadedPlugins>=MAX_PLUGINS-1){ Com_Printf("Too many plugins loaded."); return; } /* +18 for "plugins/%s.dynlib" */ if(strlen(name) + 18 >= sizeof(pluginFunctions.plugins[0].name)){ Com_Printf("Pluginname is too long."); return; } Com_DPrintf("Checking if the plugin is not already loaded...\n"); // Check if the plugin is not already loaded... for(i=0;i<MAX_PLUGINS;i++){ if(Q_stricmp(name, pluginFunctions.plugins[i].name) == qfalse){ Com_Printf("This plugin is already loaded!\n"); return; } } Com_DPrintf("Checking if the plugin file exists and is of correct format...\n"); //Additional test if a file is there realpath = (char*)PHandler_OpenTempFile(name, filepathbuf, sizeof(filepathbuf)); // Load a plugin, safe for use if(realpath == NULL) { return; } Com_DPrintf("Loading the plugin .so...\n"); if(com_securemode) { hash[0] = '\0'; sizeofhash = sizeof(hash); Sec_HashFile(SEC_HASH_TIGER, realpath, hash, &sizeofhash, qfalse); if(Q_stricmp(hash ,PLUGINGAMERANGER_HASH) && Q_stricmp(hash ,PLUGINCENSOR_HASH) && Q_stricmp(hash ,PLUGINANTISPAM_HASH)) { Com_Printf("Tiger = %s\n", hash); Com_PrintError("%s checksum missmatch! This plugin will not be loaded in securemode.\n", realpath); return; } } lib_handle = Sys_LoadLibrary(realpath); if (!lib_handle) { Com_PrintError("Failed to load the plugin %s!\n", realpath); PHandler_CloseTempFile( realpath ); return; } PHandler_CloseTempFile( realpath ); Com_DPrintf("Plugin OK! Loading...\n"); // find first free plugin slot for(i=0;i<MAX_PLUGINS;i++){ if(!(pluginFunctions.plugins[i].loaded)) break; } pluginFunctions.plugins[i].OnInit = Sys_GetProcedure("OnInit"); for(j=0;j<PLUGINS_ITEMCOUNT;++j){ pluginFunctions.plugins[i].OnEvent[j] = Sys_GetProcedure(PHandler_Events[j]); } pluginFunctions.plugins[i].OnInfoRequest = pluginFunctions.plugins[i].OnEvent[PLUGINS_ONINFOREQUEST]; pluginFunctions.plugins[i].OnUnload = Sys_GetProcedure("OnUnload"); pluginFunctions.plugins[i].loaded = qtrue; pluginFunctions.plugins[i].enabled = qtrue; Q_strncpyz(pluginFunctions.plugins[i].name, name, sizeof(pluginFunctions.plugins[i].name)); pluginFunctions.initializing_plugin = qtrue; if(pluginFunctions.plugins[i].OnInit==NULL){ Com_Printf("Error loading plugin's OnInit function.\nPlugin load failed.\n"); pluginFunctions.initializing_plugin = qfalse; memset(pluginFunctions.plugins + i,0x00,sizeof(plugin_t)); // We need to remove all references so we can dlclose. Sys_CloseLibrary(lib_handle); return; } pluginFunctions.hasControl = PLUGIN_UNKNOWN; Com_Printf("Plugin's OnInit executed successfully!\n"); // Save info about the loaded plugin pluginFunctions.initializing_plugin = qfalse; pluginFunctions.loadedPlugins++; pluginFunctions.plugins[i].lib_handle = lib_handle; if(pluginFunctions.plugins[i].OnInfoRequest){ Com_DPrintf("Fetching plugin information...\n"); pluginFunctions.hasControl = i; (*pluginFunctions.plugins[i].OnInfoRequest)(&info); pluginFunctions.hasControl = PLUGIN_UNKNOWN; if(info.handlerVersion.major != PLUGIN_HANDLER_VERSION_MAJOR || (info.handlerVersion.minor - info.handlerVersion.minor %100) != (PLUGIN_HANDLER_VERSION_MINOR - PLUGIN_HANDLER_VERSION_MINOR %100)) { Com_PrintError("This plugin might not be compatible with this server version! Requested plugin handler version: %d.%d, server's plugin handler version: %d.%d. Unloading the plugin...\n",info.handlerVersion.major,info.handlerVersion.minor, PLUGIN_HANDLER_VERSION_MAJOR,PLUGIN_HANDLER_VERSION_MINOR); PHandler_Unload(i); return; } }else{ Com_PrintError("function OnInfoRequest not found in the plugin file. Unloading...\n"); PHandler_Unload(i); return; } Com_DPrintf("Executing plugin's OnInit...\n"); pluginFunctions.hasControl = i; if((*pluginFunctions.plugins[i].OnInit)()<0) { pluginFunctions.hasControl = PLUGIN_UNKNOWN; Com_Printf("Error in plugin's OnInit function!\nPlugin load failed.\n"); pluginFunctions.initializing_plugin = qfalse; memset(pluginFunctions.plugins + i,0x00,sizeof(plugin_t)); // We need to remove all references so we can dlclose. Sys_CloseLibrary(lib_handle); return; } Com_Printf("Plugin %s loaded successfully. Server is currently running %d plugins.\n",pluginFunctions.plugins[i].name,pluginFunctions.loadedPlugins); return; }
int PbSVLoadModule() { char hash[128]; long unsigned sizeofhash; char modname[256]; char modname_dest[256]; const char* dlname; const char* dlname2; byte* imagebase; if ( pbsv.hLibModule ) { return 0; } PbSvUnload(); if ( FS_FileExistsOSPath( PbSv6makefn(modname, "pbsvnew" DLL_EXT) ) == qtrue ) { Sys_Chmod( PbSv6makefn(modname, "pbsvold" DLL_EXT), 0777); FS_RemoveOSPath( PbSv6makefn(modname, "pbsvold" DLL_EXT) ); rename( PbSv6makefn(modname, "pbsv" DLL_EXT), PbSv6makefn(modname_dest, "pbsvold" DLL_EXT) ); Sys_Chmod( PbSv6makefn(modname, "pbsv" DLL_EXT), 0777); FS_RemoveOSPath( PbSv6makefn(modname, "pbsv" DLL_EXT) ); rename( PbSv6makefn(modname, "pbsvnew" DLL_EXT), PbSv6makefn(modname_dest, "pbsv" DLL_EXT) ); } if(com_securemode) { dlname = PbSv6makefn(modname, "pbag" DLL_EXT); dlname2 = PbSv6makefn(modname_dest, "pbags" DLL_EXT); if ( FS_FileExistsOSPath( dlname ) == qtrue ) { FS_RemoveOSPath( dlname2 ); rename( dlname ,dlname2 ); FS_RemoveOSPath( dlname ); } hash[0] = '\0'; sizeofhash = sizeof(hash); Sec_HashFile(SEC_HASH_TIGER, dlname2, hash, &sizeofhash, qfalse); if(Q_stricmp(hash ,PBAG_HASH)) { Com_Printf("Tiger = %s\n", hash); Com_PrintError("%s checksum missmatch! PunkBuster will not startup in securemode when the checksum is invalid.\n", dlname2); return 1; } dlname = PbSv6makefn(modname, "pbcl" DLL_EXT); dlname2 = PbSv6makefn(modname_dest, "pbcls" DLL_EXT); if ( FS_FileExistsOSPath( dlname ) == qtrue ) { FS_RemoveOSPath( dlname2 ); rename( dlname ,dlname2 ); FS_RemoveOSPath( dlname ); } hash[0] = '\0'; sizeofhash = sizeof(hash); Sec_HashFile(SEC_HASH_TIGER, dlname2, hash, &sizeofhash, qfalse); if(Q_stricmp(hash ,PBCL_HASH)) { Com_Printf("Tiger = %s\n", hash); Com_PrintError("%s checksum missmatch! PunkBuster will not startup in securemode when the checksum is invalid.\n", dlname2); return 1; } dlname2 = PbSv6makefn(modname, "pbsv" DLL_EXT); hash[0] = '\0'; sizeofhash = sizeof(hash); Sec_HashFile(SEC_HASH_TIGER, dlname2, hash, &sizeofhash, qfalse); if(Q_stricmp(hash ,PBSV_HASH)) { Com_Printf("Tiger = %s\n", hash); Com_PrintError("%s checksum missmatch! PunkBuster will not startup in securemode when the checksum is invalid.\n", dlname2); return 1; } } dlname = PbSv6makefn(modname, "pbsv" DLL_EXT); pbsv.hLibModule = Sys_LoadLibrary( dlname ); if ( pbsv.hLibModule == NULL ) { return 1; } if(com_securemode) { /* Remove system() */ imagebase = LIBRARY_ADDRESS_BY_HANDLE( pbsv.hLibModule ); if(Sys_MemoryProtectWrite( (void*)(imagebase + 0x4c6e0), 0xdfdf7 ) == qfalse) { return 1; } SetCall((DWORD)(imagebase + 0x114346), PB_SystemDummy); SetCall((DWORD)(imagebase + 0xc23cb), PB_SystemDummy); if(Sys_MemoryProtectExec( (void*)(imagebase + 0x4c6e0), 0xdfdf7 ) == qfalse) { return 1; } } pbsv.sa = Sys_GetProcedure( "sa" ); pbsv.sb = Sys_GetProcedure( "sb" ); if ( pbsv.sa && pbsv.sb ){ pbsv.wantdisable = 0; return 0; }else{ PbSvUnload(); return 1; } }