const char* PHandler_OpenTempFile(char* name, char* fullfilepath, int fplen){ // Load a plugin, safe for use void *buf; int len; int wlen; char* file; char tmpfile[MAX_QPATH]; char filepath[MAX_QPATH]; Com_sprintf(filepath, sizeof(filepath),"plugins/%s" DLL_EXT, name); len = FS_ReadFile(filepath, &buf); if(len < 100) len = FS_SV_ReadFile( filepath, &buf ); if(len < 100) { Com_Printf("No such file found: %s. Can not load this plugin.\n", filepath); return NULL; } if(PHandler_VerifyPlugin(buf, len) == qfalse) { Com_Printf("%s is not a plugin file or is corrupt or contains disallowed functions.\n", filepath); FS_FreeFile(buf); return NULL; } Com_sprintf(tmpfile, sizeof(tmpfile), "plugin.%s.tmp", name); /* If there is already such a file remove it now */ file = FS_SV_GetFilepath( tmpfile, fullfilepath, fplen ); if(file) { FS_RemoveOSPath(file); file = FS_SV_GetFilepath( tmpfile, fullfilepath, fplen ); if(file) { FS_RemoveOSPath(file); } } wlen = FS_SV_HomeWriteFile( tmpfile, buf, len); if(wlen != len) { Com_PrintError("fs_homepath is readonly. Can not load this plugin.\n"); FS_FreeFile(buf); return NULL; } //Additional test if a file is there and creation of full filepath FS_FreeFile(buf); return FS_SV_GetFilepath( tmpfile, fullfilepath, fplen ); }
void PHandler_CloseTempFile(char* filepath) { if(!com_developer || com_developer->integer == 0) FS_RemoveOSPath(filepath); }
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; } }
void Sec_Update( qboolean getbasefiles ){ char buff[SEC_UPDATE_INITIALBUFFSIZE]; char *ptr,*ptr2, *testfile; char filepathbuf[MAX_OSPATH]; char baseurl[1024]; char name1[256],name2[256]; sec_file_t files, *currFile = &files; qboolean dlExec = qfalse; int len; char hash[128]; long unsigned size; ftRequest_t* filetransferobj; ftRequest_t* curfileobj; int transret; mvabuf; if(!Sec_Initialized()){ return; } #ifdef CAN_UPDATE Com_Printf("\n-----------------------------\n"); Com_Printf(" CoD4X Auto Update\n"); Com_Printf(" Current version: %g\n",SEC_VERSION); Com_Printf(" Current build: %d\n",BUILD_NUMBER); Com_Printf(" Current type: %s\n",SEC_TYPE == 's' ? "stable " : "experimental"); Com_Printf("-----------------------------\n\n"); canupdate = Cvar_RegisterBool("allowupdating", qtrue, 0, "This enables autoupdating of CoD4 server with new versions."); if(getbasefiles == qtrue) { Com_sprintf(buff, sizeof(buff), "http://" SEC_UPDATE_HOST SEC_UPDATE_GETGROUNDVERSION); }else{ if(canupdate->boolean == qfalse) return; Com_sprintf(buff, sizeof(buff), "http://" SEC_UPDATE_HOST SEC_UPDATE_GETVERSION); } #else if(getbasefiles == qtrue) { Com_sprintf(buff, sizeof(buff), "http://" SEC_UPDATE_HOST SEC_UPDATE_GETGROUNDVERSION); }else{ return; } #endif filetransferobj = FileDownloadRequest( buff ); if(filetransferobj == NULL){ return; } do { transret = FileDownloadSendReceive( filetransferobj ); usleep(20000); } while (transret == 0); if(transret < 0) { FileDownloadFreeRequest(filetransferobj); return; } /* Need to catch errors */ // FS_WriteFile("tmp.txt", va("%d", status), 1); // TODO: Do something with the status? // FS_WriteFile("tmp2.txt", packet.header, packet.headerLength); // FS_WriteFile("tmp3.txt", packet.content, packet.contentLength); if(filetransferobj->code <= 0){ Com_PrintError("Receiving data. Error code: %d.\n", filetransferobj->code); FileDownloadFreeRequest(filetransferobj); return; } if(filetransferobj->code == 204){ Com_Printf("\nServer is up to date.\n\n"); FileDownloadFreeRequest(filetransferobj); return; } else if(filetransferobj->code != 200){ Com_PrintWarning("The update server's malfunction.\nStatus code: %d.\n", filetransferobj->code); FileDownloadFreeRequest(filetransferobj); return; } Com_Memset(&files, 0, sizeof(files)); /* We need to parse filenames etc */ ptr = Sec_StrTok((char*)(filetransferobj->recvmsg.data + filetransferobj->headerLength),"\n",42); // Yes, 42. if(ptr == NULL || Q_stricmpn("baseurl: ", ptr, 9)) { Com_PrintWarning("Sec_Update: Corrupt data from update server. Update aborted.\n"); FileDownloadFreeRequest(filetransferobj); return; } Q_strncpyz(baseurl, ptr +9, sizeof(baseurl)); ptr = Sec_StrTok(NULL,"\n",42); // Yes, 42 again. while(ptr != NULL){ currFile->next = Sec_GMalloc(sec_file_t,1); currFile = currFile->next; Com_Memset(currFile,0,sizeof(sec_file_t)); ptr2 = strchr(ptr,' '); if(ptr2 == NULL){ Com_PrintWarning("Sec_Update: Corrupt data from update server. Update aborted.\nDebug:\"%s\"\n",ptr); FileDownloadFreeRequest(filetransferobj); return; } *ptr2++ = 0; Q_strncpyz(currFile->path,ptr,sizeof(currFile->path)); ptr = ptr2; ptr2 = strchr(ptr,' '); if(ptr2 == NULL){ Com_PrintWarning("Sec_Update: Corrupt data from update server. Update aborted.\nDebug:\"%s\"\n",ptr); FileDownloadFreeRequest(filetransferobj); return; } *ptr2++ = 0; if(!isInteger(ptr, 0)){ Com_PrintWarning("Sec_Update: Corrupt data from update server - size is not a number. Update aborted.\nDebug:\"%s\"\n",ptr); FileDownloadFreeRequest(filetransferobj); return; } currFile->size = atoi(ptr); Q_strncpyz(currFile->hash,ptr2,sizeof(currFile->hash)); Q_strncpyz(currFile->name,currFile->path, sizeof(currFile->name)); //printf("DEBUG: File to download: link: \"%s\", name: \"%s\", size: %d, hash: \"%s\"\n\n",file.path,file.name,file.size,file.hash); Com_sprintf(buff, sizeof(buff), SEC_UPDATE_DOWNLOAD(baseurl, currFile->path)); curfileobj = FileDownloadRequest(buff); if(curfileobj == NULL) { FileDownloadFreeRequest(filetransferobj); return; } Com_Printf("Downloading file: \"%s\"\n\n",currFile->name); do { transret = FileDownloadSendReceive( curfileobj ); Com_Printf("%s", FileDownloadGenerateProgress( curfileobj )); usleep(20000); } while (transret == 0); Com_Printf("\n"); if(transret < 0) { FileDownloadFreeRequest(curfileobj); FileDownloadFreeRequest(filetransferobj); return; } Q_strncpyz(buff,currFile->name, sizeof(buff)); Q_strcat(buff, sizeof(buff),".new"); if(curfileobj->code != 200){ Com_PrintError("Downloading has failed! Error code: %d. Update aborted.\n", curfileobj->code); FileDownloadFreeRequest(filetransferobj); FileDownloadFreeRequest(curfileobj); return; } len = FS_SV_BaseWriteFile(buff, curfileobj->recvmsg.data + curfileobj->headerLength, curfileobj->contentLength); if(len != curfileobj->contentLength){ len = FS_SV_HomeWriteFile(buff, curfileobj->recvmsg.data + curfileobj->headerLength, curfileobj->contentLength); if(len != curfileobj->contentLength) { Com_PrintError("Opening \"%s\" for writing! Update aborted.\n",buff); FileDownloadFreeRequest(filetransferobj); FileDownloadFreeRequest(curfileobj); return; } } ptr = Sec_StrTok(NULL,"\n",42); // Yes, 42 again. size = sizeof(hash); if(!Sec_HashMemory(SEC_HASH_SHA256, curfileobj->recvmsg.data + curfileobj->headerLength, curfileobj->contentLength, hash, &size,qfalse)){ Com_PrintError("Hashing the file \"%s\". Error code: %s.\nUpdate aborted.\n",currFile->name,Sec_CryptErrStr(SecCryptErr)); FileDownloadFreeRequest(filetransferobj); FileDownloadFreeRequest(curfileobj); return; } FileDownloadFreeRequest(curfileobj); if(!Q_strncmp(hash, currFile->hash, size)){ Com_Printf("Successfully downloaded file \"%s\".\n", currFile->name); } else{ Com_PrintError("File \"%s\" is corrupt!\nUpdate aborted.\n",currFile->name); Com_DPrintf("Hash: \"%s\", correct hash: \"%s\".\n",hash,currFile->hash); FileDownloadFreeRequest(filetransferobj); return; } } FileDownloadFreeRequest(filetransferobj); Com_Printf("All files downloaded successfully. Applying update...\n"); currFile = files.next; do{ Com_Printf("Updating file %s...\n", currFile->name); Q_strncpyz(name1, currFile->name, sizeof(name1)); Q_strcat(name1, sizeof(name1), ".old"); Q_strncpyz(name2, currFile->name, sizeof(name2)); Q_strcat(name2, sizeof(name2), ".new"); testfile = FS_SV_GetFilepath(name1, filepathbuf, sizeof(filepathbuf)); if(testfile != NULL) { // Old file exists, back it up FS_SV_BaseRemove( name1 ); FS_SV_HomeRemove( name1 ); testfile = FS_SV_GetFilepath(name1, filepathbuf, sizeof(filepathbuf)); if(testfile != NULL) { Com_PrintWarning("Couldn't remove backup file: %s\n", testfile); } if(FS_SV_HomeFileExists(name1) == qtrue) { Com_PrintError("Couldn't remove backup file from fs_homepath: %s\n", name1); } } // Check if an old file exists with this name testfile = FS_SV_GetFilepath(currFile->name, filepathbuf, sizeof(filepathbuf)); if(testfile != NULL) { // Old file exists, back it up FS_SV_Rename(currFile->name, name1); } testfile = FS_SV_GetFilepath(currFile->name, filepathbuf, sizeof(filepathbuf)); // We couldn't back it up. Now we try to just delete it. if(testfile != NULL) { FS_SV_BaseRemove( currFile->name ); FS_SV_HomeRemove( currFile->name ); testfile = FS_SV_GetFilepath( currFile->name, filepathbuf, sizeof(filepathbuf) ); if(testfile != NULL) { Com_PrintWarning("Couldn't remove file: %s\n", testfile); } if(FS_SV_HomeFileExists(currFile->name) == qtrue) { Com_PrintError("Couldn't remove file from fs_homepath: %s\n", currFile->name); Com_PrintError("Update has failed!\n"); return; } } if(Q_strncmp(currFile->name, EXECUTABLE_NAME, 15)){ /* This is not the executable file */ FS_SV_Rename(name2, currFile->name); testfile = FS_SV_GetFilepath(currFile->name, filepathbuf, sizeof(filepathbuf)); if(testfile == NULL) { Com_PrintError("Failed to rename file %s to %s\n", name2,currFile->name); Com_PrintError("Update has failed!\n"); return; } Com_Printf("Update on file %s successfully applied.\n",currFile->name); }else{ /* This is the executable file */ testfile = FS_SV_GetFilepath(name2, filepathbuf, sizeof(filepathbuf)); if(testfile == NULL) { Com_PrintError("Can not find file %s\n", name2); Com_PrintError("Update has failed!\n"); return; } if(FS_SetPermissionsExec(name2) == qfalse) { Com_PrintError("CRITICAL ERROR: failed to change mode of the file \"%s\"! Aborting, manual installation might be required.\n", name2); return; } FS_RenameOSPath(Sys_ExeFile(), va("%s.dead", Sys_ExeFile())); FS_RemoveOSPath(va("%s.dead", Sys_ExeFile())); FS_RemoveOSPath(Sys_ExeFile()); if(FS_FileExistsOSPath(Sys_ExeFile())) { Com_PrintError("Failed to delete file %s\n", Sys_ExeFile()); Com_PrintError("Update has failed!\n"); return; } FS_RenameOSPath(testfile, Sys_ExeFile()); if(!FS_FileExistsOSPath(Sys_ExeFile())) { Com_PrintError("Failed to rename file %s\n", testfile); Com_PrintError("Update has failed! Manual reinstallation of file %s is required. This server is now broken!\n", Sys_ExeFile()); return; } Com_Printf("Update on file %s successfully applied.\n", Sys_ExeFile()); dlExec = qtrue; } currFile = currFile->next; }while(currFile != NULL); Sec_FreeFileStruct(files.next); Com_Printf("Finalizing update...\n"); if(dlExec == qtrue) { Sys_Restart("System has been updated and will restart now."); }else{ FS_Restart( 0 ); } }