From 594591440bca32c72440cfcc12fed7e97b0c73a6 Mon Sep 17 00:00:00 2001 From: Eladash Date: Sat, 13 Mar 2021 03:51:40 +0200 Subject: [PATCH 1/4] GUI: Handle uppercase RAP file extension --- rpcs3/rpcs3qt/main_window.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/rpcs3/rpcs3qt/main_window.cpp b/rpcs3/rpcs3qt/main_window.cpp index 88b1d18c5bf5..972c65d3b557 100644 --- a/rpcs3/rpcs3qt/main_window.cpp +++ b/rpcs3/rpcs3qt/main_window.cpp @@ -515,7 +515,8 @@ bool main_window::InstallRapFile(const QString& path, const std::string& filenam { return false; } - return fs::copy_file(sstr(path), Emulator::GetHddDir() + "/home/" + Emu.GetUsr() + "/exdata/" + filename, true); + + return fs::copy_file(sstr(path), Emulator::GetHddDir() + "/home/" + Emu.GetUsr() + "/exdata/" + filename.substr(0, filename.find_last_of('.')) + ".rap", true); } void main_window::InstallPackages(QStringList file_paths) @@ -585,7 +586,7 @@ void main_window::InstallPackages(QStringList file_paths) } // Install rap files if available - for (const auto& rap : file_paths.filter(QRegExp(".*\\.rap"))) + for (const auto& rap : file_paths.filter(QRegExp(".*\\.rap", Qt::CaseInsensitive))) { const QFileInfo file_info(rap); const std::string rapname = sstr(file_info.fileName()); @@ -2566,7 +2567,7 @@ main_window::drop_type main_window::IsValidFile(const QMimeData& md, QStringList drop_type = drop_type::drop_pkg; } - else if (info.suffix() == "rap") + else if (info.suffix().toLower() == "rap") { if (drop_type != drop_type::drop_rap && drop_type != drop_type::drop_error) { From befa3b0c2bde10b89e96cecd7bd8db9b923dc496 Mon Sep 17 00:00:00 2001 From: Eladash Date: Sat, 13 Mar 2021 07:51:35 +0200 Subject: [PATCH 2/4] GUI: Handle all PUP files in drag-and-drop --- rpcs3/rpcs3qt/main_window.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpcs3/rpcs3qt/main_window.cpp b/rpcs3/rpcs3qt/main_window.cpp index 972c65d3b557..bfe83bdb7b4a 100644 --- a/rpcs3/rpcs3qt/main_window.cpp +++ b/rpcs3/rpcs3qt/main_window.cpp @@ -2549,7 +2549,7 @@ main_window::drop_type main_window::IsValidFile(const QMimeData& md, QStringList drop_type = drop_type::drop_dir; } - else if (info.fileName() == "PS3UPDAT.PUP") + else if (info.suffix() == "PUP") { if (list.size() != 1) { From 989b067e5461085d863ed8957669d9f4b7179ccb Mon Sep 17 00:00:00 2001 From: Eladash Date: Sat, 13 Mar 2021 08:19:22 +0200 Subject: [PATCH 3/4] GUI: Atomic RAP file installation --- rpcs3/rpcs3qt/main_window.cpp | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/rpcs3/rpcs3qt/main_window.cpp b/rpcs3/rpcs3qt/main_window.cpp index bfe83bdb7b4a..292d34d8588c 100644 --- a/rpcs3/rpcs3qt/main_window.cpp +++ b/rpcs3/rpcs3qt/main_window.cpp @@ -516,7 +516,25 @@ bool main_window::InstallRapFile(const QString& path, const std::string& filenam return false; } - return fs::copy_file(sstr(path), Emulator::GetHddDir() + "/home/" + Emu.GetUsr() + "/exdata/" + filename.substr(0, filename.find_last_of('.')) + ".rap", true); + // Copy file atomically with thread/process-safe error checking for file size + + fs::pending_file to(Emulator::GetHddDir() + "/home/" + Emu.GetUsr() + "/exdata/" + filename.substr(0, filename.find_last_of('.')) + ".rap"); + fs::file from(sstr(path)); + + if (!to.file || !from) + { + return false; + } + + to.file.write(from.to_vector()); + + if (to.file.size() < 0x10) + { + // Not a RAP file + return false; + } + + return to.commit(); } void main_window::InstallPackages(QStringList file_paths) From 7951c5a00e54820f8da57d7c14c53df449a1fdfc Mon Sep 17 00:00:00 2001 From: Eladash Date: Sat, 13 Mar 2021 08:21:18 +0200 Subject: [PATCH 4/4] SCE Decryption: Detect illegal RAP files --- rpcs3/Crypto/unself.cpp | 7 ++++++- rpcs3/Emu/Cell/Modules/sceNp.cpp | 4 ++-- rpcs3/rpcs3qt/main_window.cpp | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/rpcs3/Crypto/unself.cpp b/rpcs3/Crypto/unself.cpp index 54a70b761594..e8148574dd0e 100644 --- a/rpcs3/Crypto/unself.cpp +++ b/rpcs3/Crypto/unself.cpp @@ -1335,7 +1335,12 @@ bool SELFDecrypter::GetKeyFromRap(u8* content_id, u8* npdrm_key) } self_log.notice("Loading RAP file %s.rap", ci_str); - rap_file.read(rap_key, 0x10); + + if (rap_file.read(rap_key, 0x10) != 0x10) + { + self_log.fatal("Failed to load %s: RAP file exists but is invalid. Try reinstalling it.", rap_path); + return false; + } // Convert the RAP key. rap_to_rif(rap_key, npdrm_key); diff --git a/rpcs3/Emu/Cell/Modules/sceNp.cpp b/rpcs3/Emu/Cell/Modules/sceNp.cpp index b4dea9b9bd51..b092c11b634b 100644 --- a/rpcs3/Emu/Cell/Modules/sceNp.cpp +++ b/rpcs3/Emu/Cell/Modules/sceNp.cpp @@ -557,7 +557,7 @@ error_code sceNpDrmVerifyUpgradeLicense(vm::cptr content_id) sceNp.warning(u8"sceNpDrmVerifyUpgradeLicense(): content_id=ā€œ%sā€", content_id); - if (!fs::is_file(vfs::get("/dev_hdd0/home/" + Emu.GetUsr() + "/exdata/" + content_str + ".rap"))) + if (fs::stat_t s{}; !fs::stat(vfs::get("/dev_hdd0/home/" + Emu.GetUsr() + "/exdata/" + content_str + ".rap"), s) || s.is_directory || s.size < 0x10) { // Game hasn't been purchased therefore no RAP file present return SCE_NP_DRM_ERROR_LICENSE_NOT_FOUND; @@ -580,7 +580,7 @@ error_code sceNpDrmVerifyUpgradeLicense2(vm::cptr content_id) sceNp.warning(u8"sceNpDrmVerifyUpgradeLicense2(): content_id=ā€œ%sā€", content_id); - if (!fs::is_file(vfs::get("/dev_hdd0/home/" + Emu.GetUsr() + "/exdata/" + content_str + ".rap"))) + if (fs::stat_t s{}; !fs::stat(vfs::get("/dev_hdd0/home/" + Emu.GetUsr() + "/exdata/" + content_str + ".rap"), s) || s.is_directory || s.size < 0x10) { // Game hasn't been purchased therefore no RAP file present return SCE_NP_DRM_ERROR_LICENSE_NOT_FOUND; diff --git a/rpcs3/rpcs3qt/main_window.cpp b/rpcs3/rpcs3qt/main_window.cpp index 292d34d8588c..d512e8ac7195 100644 --- a/rpcs3/rpcs3qt/main_window.cpp +++ b/rpcs3/rpcs3qt/main_window.cpp @@ -2587,7 +2587,7 @@ main_window::drop_type main_window::IsValidFile(const QMimeData& md, QStringList } else if (info.suffix().toLower() == "rap") { - if (drop_type != drop_type::drop_rap && drop_type != drop_type::drop_error) + if (info.size() < 0x10 || (drop_type != drop_type::drop_rap && drop_type != drop_type::drop_error)) { return drop_type::drop_error; }