void GScr_SHA256(){ char hash[129]; unsigned long size; if(Scr_GetNumParam() != 1){ Scr_Error("Usage: sha256(<input text>)\n"); } char* input = Scr_GetString(0); size = sizeof(hash); if(!Sec_HashMemory(SEC_HASH_SHA256, input, strlen(input), hash, &size, qfalse)) { hash[0] = '\0'; } Scr_AddString(hash); }
const char* Auth_GetSessionId(const char* username, const char *password) { int handle; byte buff[129]; unsigned long size; handle = Auth_Authorize(username, password); if(handle < 0) { return NULL; } size = sizeof(auth_admins.admins[handle].sessionid); Com_RandomBytes(buff, sizeof(buff)); //Sec_BinaryToHex((char *)buff,sizeof(buff),salt,&size); Sec_HashMemory( SEC_HASH_SHA256, buff, sizeof(buff), auth_admins.admins[handle].sessionid, &size, qfalse ); return auth_admins.admins[handle].sessionid; }
void Auth_SetAdmin_f( void ) { const char* username; const char* password; const char* sha256; byte buff[129]; char salt[65]; unsigned long size = sizeof(salt); int power, i,uid; authData_admin_t* user; authData_admin_t* free = NULL; mvabuf; if(Cmd_Argc() != 4) { Com_Printf("Usage: %s <username> <password> <power>\n", Cmd_Argv(0)); Com_Printf( "Where username is loginname for this user\n" ); Com_Printf( "Where password is the initial 6 characters long or longer password for this user which should get changed by the user on first login\n" ); Com_Printf( "Where power is one of the following: Any number between 1 and 100\n" ); return; } username = Cmd_Argv(1); password = Cmd_Argv(2); power = atoi(Cmd_Argv(3)); if(!username || !*username || !password || strlen(password) < 6 || power < 1 || power > 100) { Com_Printf("Usage: %s <username> <password> <power>\n", Cmd_Argv(0)); Com_Printf( "Where username is loginname for this user\n" ); Com_Printf( "Where password is the initial 6 characters long or longer password for this user which should get changed by the user on first login\n" ); Com_Printf( "Where power is one of the following: Any number between 1 and 100\n" ); return; } NV_ProcessBegin(); uid = ++auth_admins.maxUID; for(i = 0, user = auth_admins.admins; i < MAX_AUTH_ADMINS; i++, user++) { if(!Q_stricmp(user->username, username)) { Com_Printf("An admin with this username is already registered\n"); return; } if(!free && !*user->username ) free = user; } if(!free) { Com_Printf("Too many registered admins. Limit is: %d\n", MAX_AUTH_ADMINS); return; } Com_RandomBytes(buff, sizeof(buff)); //Sec_BinaryToHex((char *)buff,sizeof(buff),salt,&size); Sec_HashMemory(SEC_HASH_SHA256,buff,sizeof(buff),salt,&size,qfalse); /*for(i = 0; i < sizeof(salt) -1; i++){ if(salt[i] > 126){ salt[i] -= 125; } if(salt[i] < ' '){ salt[i] += ' '; } if(salt[i] == ';') salt[i]++; if(salt[i] == '\\') salt[i]++; if(salt[i] == '%') salt[i]++; if(salt[i] == '"') salt[i]++; } salt[sizeof(salt) -1] = 0;*/ sha256 = Com_SHA256(va("%s.%s", password, salt)); Q_strncpyz(free->username, username, sizeof(free->username)); Com_Printf("Debug: 1:%s 2:%s\n", username, free->username); Q_strncpyz(free->sha256, sha256, sizeof(free->sha256)); Q_strncpyz(free->salt, (char*)salt, sizeof(free->salt)); //free->power = power; Instead: SV_RemoteCmdSetAdmin(uid, NULL, power); free->uid = uid; Com_Printf("Registered user with Name: %s Power: %d UID: %d\n", free->username, power, uid); NV_ProcessEnd(); }
void Auth_ChangeAdminPassword( int uid,const char* oldPassword,const char* password ) { const char* sha256; byte buff[129]; char salt[65]; unsigned long size = sizeof(salt); authData_admin_t *user, *user2; int i; //int uid = -1; mvabuf; if(!password || strlen(password) < 6) { Com_Printf("Error: the new password must have at least 6 characters\n"); return; } NV_ProcessBegin(); for(i = 0, user2 = auth_admins.admins; i < MAX_AUTH_ADMINS; i++, user2++) { if(*user2->username && user2->uid == uid) { user = user2; } } if(user == NULL) { Com_Printf("Error: unknown admin @%d!\n",uid); return; } Com_RandomBytes(buff, sizeof(buff)); Sec_HashMemory(SEC_HASH_SHA256,buff,sizeof(buff),salt,&size,qfalse); /*salt[sizeof(salt) -1] = 0; // Not needed for(i = 0; i < sizeof(salt) -1; i++){ if(salt[i] > 126){ salt[i] -= 125; } if(salt[i] < ' '){ salt[i] += ' '; } if(salt[i] == ';') salt[i]++; if(salt[i] == '\\') salt[i]++; if(salt[i] == '%') salt[i]++; if(salt[i] == '"') salt[i]++; }*/ sha256 = Com_SHA256(va("%s.%s", password, salt)); Q_strncpyz(user->sha256, sha256, sizeof(user->sha256)); Q_strncpyz(user->salt, (char *)salt, sizeof(user->salt)); NV_ProcessEnd(); Com_Printf("Password changed to: %s\n", password); }
/* ============= Sys_LoadImage ============= */ qboolean Sys_LoadImage( ){ byte *fileimage; int len; char hash[128]; long unsigned sizeofhash; /* Is this file here ? */ len = FS_FOpenFileRead(BIN_FILENAME, NULL); if(len != DLLMOD_FILESIZE) {/* Nope !*/ Sec_Update( qtrue ); len = FS_FOpenFileRead(BIN_FILENAME, NULL); if(len != DLLMOD_FILESIZE) {/* Nope !*/ Com_PrintError("Failed to load the CoD4 Game. Can not startup the game\n"); return qfalse; } } Sec_Update( qfalse ); len = FS_ReadFile(BIN_FILENAME, (void**)&fileimage); if(!fileimage) { Com_PrintError("Couldn't open "BIN_FILENAME". CoD4 can not startup.\n"); return qfalse; } if(len != DLLMOD_FILESIZE) { Com_PrintError(BIN_FILENAME" has an invalid length! CoD4 can not startup.\n"); FS_FreeFile(fileimage); return qfalse; } sizeofhash = sizeof(hash); Sec_HashMemory(SEC_HASH_TIGER, fileimage, len, hash, &sizeofhash, qfalse); if(Q_stricmp(hash ,DLLMOD_HASH)) { Com_Printf("Tiger = %s\n", hash); Com_PrintError(BIN_FILENAME" checksum missmatch! CoD4 can not startup.\n"); FS_FreeFile(fileimage); return qfalse; } Com_Memcpy(BIN_SECT_TEXT_START, fileimage + BIN_SECT_TEXT_FOFFSET, BIN_SECT_TEXT_LENGTH); Com_Memcpy(BIN_SECT_RODATA_START, fileimage + BIN_SECT_RODATA_FOFFSET, BIN_SECT_RODATA_LENGTH); Com_Memcpy(BIN_SECT_DATA_START, fileimage + BIN_SECT_DATA_FOFFSET, BIN_SECT_DATA_LENGTH); Com_Memset(BIN_SECT_PLT_START, 0xCC, BIN_SECT_PLT_LENGTH); Sys_CoD4Linker(); FS_FreeFile(fileimage); if(!Sys_PatchImage()) { return qfalse; } /* The order here is crucial as this sections will overlap */ if(Sys_MemoryProtectReadonly(BIN_SECT_RODATA_START, BIN_SECT_RODATA_LENGTH) == qfalse) { FS_FreeFile(fileimage); return qfalse; } if(Sys_MemoryProtectWrite(BIN_SECT_DATA_START, BIN_SECT_DATA_LENGTH) == qfalse) { FS_FreeFile(fileimage); return qfalse; } if(Sys_MemoryProtectWrite(BIN_SECT_BSS_START, BIN_SECT_BSS_LENGTH) == qfalse) { FS_FreeFile(fileimage); return qfalse; } /* 4 bytes is gap between .plt end and .text start */ if(Sys_MemoryProtectExec(BIN_SECT_PLT_START, BIN_SECT_PLT_LENGTH + BIN_SECT_TEXT_LENGTH + 4) == qfalse) { FS_FreeFile(fileimage); return qfalse; } Sys_ImageRunInitFunctions(); return qtrue; }
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 ); } }