-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Deny PKG installation without RAP #17828
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1068,6 +1068,37 @@ bool SELFDecrypter::DecryptNPDRM(u8 *metadata, u32 metadata_size) | |
| return true; | ||
| } | ||
|
|
||
| std::string SELFDecrypter::GetRapFilePath() | ||
| { | ||
| // Check if we have a valid NPDRM control info structure. | ||
| // If not, the data has no NPDRM layer. | ||
| const NPD_HEADER* npd = GetNPDHeader(); | ||
| if (!npd) | ||
| { | ||
| self_log.trace("No NPDRM control info found!"); | ||
| return {}; | ||
| } | ||
|
|
||
| if (npd->license == 1) // Network license. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Switch |
||
| { | ||
| return rpcs3::utils::get_rap_file_path(npd->content_id); | ||
| } | ||
| else if (npd->license == 2) // Local license. | ||
| { | ||
| return rpcs3::utils::get_rap_file_path(npd->content_id); | ||
| } | ||
| else if (npd->license == 3) // Free license. | ||
| { | ||
| // | ||
| } | ||
| else | ||
| { | ||
| self_log.error("Invalid NPDRM license type!"); | ||
| } | ||
|
|
||
| return {}; | ||
| } | ||
|
|
||
| const NPD_HEADER* SELFDecrypter::GetNPDHeader() const | ||
| { | ||
| // Parse the control info structures to find the NPDRM control info. | ||
|
|
@@ -1435,6 +1466,46 @@ fs::file decrypt_self(const fs::file& elf_or_self, const u8* klic_key, SelfAddit | |
| return {}; | ||
| } | ||
|
|
||
| std::string get_rap_file_path_of_self(const fs::file& elf_or_self) | ||
| { | ||
| if (!elf_or_self) | ||
| { | ||
| return {}; | ||
| } | ||
|
|
||
| elf_or_self.seek(0); | ||
|
|
||
| // Check SELF header first. Check for a debug SELF. | ||
| u32 file_type = umax; | ||
| elf_or_self.read_at(0, &file_type, sizeof(file_type)); | ||
|
|
||
| if (file_type == "SCE\0"_u32) | ||
| { | ||
| if (fs::file res = CheckDebugSelf(elf_or_self)) | ||
| { | ||
| return {}; | ||
| } | ||
|
|
||
| // Check the ELF file class (32 or 64 bit). | ||
| const bool isElf32 = IsSelfElf32(elf_or_self); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. snake_case |
||
|
|
||
| // Start the decrypter on this SELF file. | ||
| SELFDecrypter self_dec(elf_or_self); | ||
|
|
||
| // Load the SELF file headers. | ||
| if (!self_dec.LoadHeaders(isElf32, nullptr)) | ||
| { | ||
| self_log.error("Failed to load SELF file headers!"); | ||
| return {}; | ||
| } | ||
|
|
||
| // Load and decrypt the SELF file metadata. | ||
| return self_dec.GetRapFilePath(); | ||
| } | ||
|
|
||
| return {}; | ||
| } | ||
|
|
||
| bool verify_npdrm_self_headers(const fs::file& self, u8* klic_key, NPD_HEADER* npd_out) | ||
| { | ||
| if (!self) | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -892,7 +892,7 @@ bool main_window::InstallPackages(QStringList file_paths, bool from_boot) | |||||
| // Install rap files if available | ||||||
| int installed_rap_and_edat_count = 0; | ||||||
|
|
||||||
| const auto install_filetype = [&installed_rap_and_edat_count, &file_paths](const std::string extension) | ||||||
| const auto install_filetype = [this, &installed_rap_and_edat_count, &file_paths](const std::string extension) | ||||||
| { | ||||||
| const QString pattern = QString(".*\\.%1").arg(QString::fromStdString(extension)); | ||||||
| for (const QString& file : file_paths.filter(QRegularExpression(pattern, QRegularExpression::PatternOption::CaseInsensitiveOption))) | ||||||
|
|
@@ -902,6 +902,13 @@ bool main_window::InstallPackages(QStringList file_paths, bool from_boot) | |||||
|
|
||||||
| if (InstallFileInExData(extension, file, filename)) | ||||||
| { | ||||||
| if (filename == last_rap_file_needed_for_pkg) | ||||||
| { | ||||||
| file_paths.append(last_pkg_path_postponed_due_to_missing_rap); | ||||||
| last_rap_file_needed_for_pkg = {}; | ||||||
| last_pkg_path_postponed_due_to_missing_rap = {}; | ||||||
| } | ||||||
|
|
||||||
| gui_log.success("Successfully copied %s file: %s", extension, filename); | ||||||
| installed_rap_and_edat_count++; | ||||||
| } | ||||||
|
|
@@ -1005,10 +1012,6 @@ bool main_window::HandlePackageInstallation(QStringList file_paths, bool from_bo | |||||
| } | ||||||
| gui_log.notice("About to install packages:\n%s", fmt::merge(path_vec, "\n")); | ||||||
|
|
||||||
| progress_dialog pdlg(tr("RPCS3 Package Installer"), tr("Installing package, please wait..."), tr("Cancel"), 0, 1000, false, this); | ||||||
| pdlg.setAutoClose(false); | ||||||
| pdlg.show(); | ||||||
|
|
||||||
| package_install_result result = {}; | ||||||
|
|
||||||
| auto get_app_info = [](compat::package_info& package) | ||||||
|
|
@@ -1047,6 +1050,53 @@ bool main_window::HandlePackageInstallation(QStringList file_paths, bool from_bo | |||||
| readers.emplace_back(info.path.toStdString()); | ||||||
| } | ||||||
|
|
||||||
| std::string missing_licenses; | ||||||
| std::string missing_licenses_short; | ||||||
|
|
||||||
| for (const auto& reader : readers) | ||||||
| { | ||||||
| if (std::string filepath = reader.gep_needed_rap_file_path(); !filepath.empty() && fs::is_file(filepath)) | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. shouldn't this be !fs::is_file ?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, this is a debug change that sleeped 👍 |
||||||
| { | ||||||
| missing_licenses += filepath; | ||||||
| missing_licenses += "\n"; | ||||||
|
|
||||||
| if (std::count(missing_licenses_short.begin(), missing_licenses_short.end(), '\n') < 5) | ||||||
| { | ||||||
| missing_licenses_short += std::string_view(filepath).substr(filepath.find_last_of(fs::delim) + 1); | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's the purpose of casting to stringview here? |
||||||
| missing_licenses_short += "\n"; | ||||||
| } | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| if (!missing_licenses.empty()) | ||||||
| { | ||||||
| gui_log.fatal("Failed to locate the game license file(s):\n%s" | ||||||
Megamouse marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| "\nEnsure the .rap license file is placed in the dev_hdd0/home/%s/exdata folder with a lowercase file extension." | ||||||
| "\nIf you need assistance on dumping the license file from your PS3, read our quickstart guide: https://rpcs3.net/quickstart", missing_licenses, Emu.GetUsr()); | ||||||
|
|
||||||
| QString error = tr("Failed to locate the game license file(s):\n\n%1\nEnsure the .rap license file(s) are placed in the dev_hdd0 folder with a lowercase file extension.").arg(QString::fromStdString(missing_licenses_short)); | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
|
||||||
| QMessageBox* mb = new QMessageBox(QMessageBox::Warning, tr("PKG Installer: Missing License(s) For PKG(s)"), error, QMessageBox::Ok, this, Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint | Qt::WindowStaysOnTopHint); | ||||||
| mb->setAttribute(Qt::WA_DeleteOnClose); | ||||||
| mb->open(); | ||||||
|
|
||||||
| if (readers.size() == 1) | ||||||
| { | ||||||
| last_pkg_path_postponed_due_to_missing_rap = packages[0].path; | ||||||
| missing_licenses_short.pop_back(); // Remove newline | ||||||
| last_rap_file_needed_for_pkg = QString::fromStdString(missing_licenses_short); | ||||||
| } | ||||||
|
|
||||||
| return false; | ||||||
| } | ||||||
|
|
||||||
| last_pkg_path_postponed_due_to_missing_rap = {}; | ||||||
| last_rap_file_needed_for_pkg = {}; | ||||||
|
|
||||||
| progress_dialog pdlg(tr("RPCS3 Package Installer"), tr("Installing package, please wait..."), tr("Cancel"), 0, 1000, false, this); | ||||||
| pdlg.setAutoClose(false); | ||||||
| pdlg.show(); | ||||||
|
|
||||||
| std::deque<std::string> bootable_paths; | ||||||
|
|
||||||
| // Run PKG unpacking asynchronously | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -51,6 +51,9 @@ class main_window : public QMainWindow | |||||||||
| int m_other_slider_pos = 0; | ||||||||||
| std::function<void()> m_notify_batch_game_action_cb; | ||||||||||
|
|
||||||||||
| QString last_pkg_path_postponed_due_to_missing_rap; | ||||||||||
| QString last_rap_file_needed_for_pkg; | ||||||||||
|
Comment on lines
+54
to
+55
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What does this do ? too lazy
Suggested change
|
||||||||||
|
|
||||||||||
| QIcon m_app_icon; | ||||||||||
| QIcon m_icon_play; | ||||||||||
| QIcon m_icon_pause; | ||||||||||
|
|
||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.