diff --git a/cmake/BuildInstall.cmake b/cmake/BuildInstall.cmake index 4a7fec9..d8d9faa 100644 --- a/cmake/BuildInstall.cmake +++ b/cmake/BuildInstall.cmake @@ -3,7 +3,11 @@ # ========================= if(LINUX AND NOT MINGW) + if(WITH_GUI) + install(TARGETS palera1n RUNTIME DESTINATION usr/bin) + else() install(TARGETS palera1n RUNTIME DESTINATION bin) + endif() elseif(IOS) install(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/Debug-iphoneos/palera1n.app/palera1n" DESTINATION bin) elseif(APPLE AND WITH_GUI) @@ -31,8 +35,36 @@ elseif(MINGW) endif() if((LINUX AND NOT MINGW) OR IOS OR (APPLE AND NOT IOS AND NOT WITH_GUI)) - install(FILES "${CMAKE_SOURCE_DIR}/docs/palera1n.1" DESTINATION share/man/man1) - install(FILES "${CMAKE_SOURCE_DIR}/docs/p1ctl.8" DESTINATION share/man/man8) + install(FILES "${CMAKE_SOURCE_DIR}/docs/palera1n.1" DESTINATION usr/share/man/man1) + install(FILES "${CMAKE_SOURCE_DIR}/docs/p1ctl.8" DESTINATION usr/share/man/man8) +endif() + +if((LINUX AND NOT MINGW) OR IOS OR (APPLE AND NOT IOS AND WITH_GUI)) + include(InstallRequiredSystemLibraries) + install( + FILES "${CMAKE_CURRENT_SOURCE_DIR}/resources/in.palera.palera1n.desktop" + DESTINATION share/applications + ) + + install( + FILES "${CMAKE_CURRENT_SOURCE_DIR}/resources/icons/hicolor/64x64/apps/in.palera.palera1n.png" + DESTINATION usr/share/icons/hicolor/64x64/apps + ) + + install( + FILES "${CMAKE_CURRENT_SOURCE_DIR}/resources/icons/hicolor/128x128/apps/in.palera.palera1n.png" + DESTINATION usr/share/icons/hicolor/128x128/apps + ) + + install( + FILES "${CMAKE_CURRENT_SOURCE_DIR}/resources/icons/hicolor/256x256/apps/in.palera.palera1n.png" + DESTINATION usr/share/icons/hicolor/256x256/apps + ) + + install( + FILES "${CMAKE_CURRENT_SOURCE_DIR}/resources/icons/hicolor/512x512/apps/in.palera.palera1n.png" + DESTINATION usr/share/icons/hicolor/512x512/apps + ) endif() set(CPACK_PACKAGE_NAME "palera1n") @@ -68,7 +100,11 @@ elseif(APPLE AND WITH_GUI) else() set(CPACK_PACKAGING_INSTALL_PREFIX "/") set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY OFF) - set(CPACK_GENERATOR "TGZ") + if(WITH_GUI) + include("${CMAKE_SOURCE_DIR}/cmake/LinuxDeploy.cmake") + else() + set(CPACK_GENERATOR "TGZ") + endif() endif() include(CPack) diff --git a/cmake/LinuxDeploy.cmake b/cmake/LinuxDeploy.cmake new file mode 100644 index 0000000..d172f5f --- /dev/null +++ b/cmake/LinuxDeploy.cmake @@ -0,0 +1,111 @@ +# cmake/LinuxDeploy.cmake + +include(FetchContent) + +set(LINUXDEPLOY_URL + "https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage" +) + +set(LINUXDEPLOY + "${CMAKE_BINARY_DIR}/linuxdeploy" +) + +if(NOT EXISTS "${LINUXDEPLOY}") + message(STATUS "Downloading linuxdeploy...") + + file(DOWNLOAD + "${LINUXDEPLOY_URL}" + "${LINUXDEPLOY}" + SHOW_PROGRESS + STATUS LINUXDEPLOY_DOWNLOAD_STATUS + ) + + list(GET LINUXDEPLOY_DOWNLOAD_STATUS 0 LINUXDEPLOY_DOWNLOAD_RESULT) + + if(NOT LINUXDEPLOY_DOWNLOAD_RESULT EQUAL 0) + list(GET LINUXDEPLOY_DOWNLOAD_STATUS 1 LINUXDEPLOY_DOWNLOAD_ERROR) + + message(FATAL_ERROR + "Failed to download linuxdeploy: ${LINUXDEPLOY_DOWNLOAD_ERROR}" + ) + endif() +endif() + +file( + CHMOD "${LINUXDEPLOY}" + FILE_PERMISSIONS + OWNER_READ OWNER_WRITE OWNER_EXECUTE + GROUP_READ GROUP_EXECUTE + WORLD_READ WORLD_EXECUTE +) + +set(CPACK_GENERATOR "External") +set(CPACK_EXTERNAL_ENABLE_STAGING YES) + +set(CPACK_EXTERNAL_PACKAGE_SCRIPT + "${CMAKE_CURRENT_BINARY_DIR}/LinuxDeploy-package.cmake" +) + +set(LINUXDEPLOY_SCRIPT [=[ +set(APPDIR "${CPACK_TEMPORARY_DIRECTORY}") +set(OUTPUT_DIR "@CMAKE_BINARY_DIR@") + +set(DESKTOP_FILE + "${APPDIR}/share/applications/in.palera.palera1n.desktop" +) + +message(STATUS "Running linuxdeploy") +message(STATUS "AppDir: ${APPDIR}") +message(STATUS "Output: ${OUTPUT_DIR}") + +execute_process( + COMMAND + "@LINUXDEPLOY@" + "--appdir=${APPDIR}" + "--desktop-file=${DESKTOP_FILE}" + "--output=appimage" + WORKING_DIRECTORY "${OUTPUT_DIR}" + RESULT_VARIABLE RESULT + OUTPUT_VARIABLE OUTPUT + ERROR_VARIABLE ERROR +) + +if(OUTPUT) + message(STATUS "${OUTPUT}") +endif() + +if(ERROR) + message(STATUS "${ERROR}") +endif() + +if(NOT RESULT EQUAL 0) + message(FATAL_ERROR + "linuxdeploy failed with exit code ${RESULT}" + ) +endif() + +message(STATUS + "AppImage generated in ${OUTPUT_DIR}" +) +]=]) + +string( + REPLACE + "@LINUXDEPLOY@" + "${LINUXDEPLOY}" + LINUXDEPLOY_SCRIPT + "${LINUXDEPLOY_SCRIPT}" +) + +string( + REPLACE + "@CMAKE_BINARY_DIR@" + "${CMAKE_BINARY_DIR}" + LINUXDEPLOY_SCRIPT + "${LINUXDEPLOY_SCRIPT}" +) + +file(GENERATE + OUTPUT "${CPACK_EXTERNAL_PACKAGE_SCRIPT}" + CONTENT "${LINUXDEPLOY_SCRIPT}" +) diff --git a/embedded/add_udev_rules.sh b/embedded/add_udev_rules.sh new file mode 100644 index 0000000..d6e2c4e --- /dev/null +++ b/embedded/add_udev_rules.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +set -e + +cat > /etc/udev/rules.d/turdusra1n.rules <<'EOF' +SUBSYSTEM=="usb", ATTRS{idVendor}=="05ac", ATTRS{idProduct}=="1227", GROUP="plugdev", MODE="0666" +SUBSYSTEM=="usb", ATTRS{idVendor}=="05ac", ATTRS{idProduct}=="1338", GROUP="plugdev", MODE="0666" +SUBSYSTEM=="usb", ATTRS{idVendor}=="05ac", ATTRS{idProduct}=="4141", GROUP="plugdev", MODE="0666" +SUBSYSTEM=="usb", ATTRS{idVendor}=="05ac", ATTRS{idProduct}=="1281", GROUP="plugdev", MODE="0666" +EOF + +getent group plugdev >/dev/null 2>&1 || groupadd plugdev +usermod -aG plugdev "$USER" + +udevadm control --reload-rules +udevadm trigger diff --git a/resources/icons/hicolor/128x128/apps/in.palera.palera1n.png b/resources/icons/hicolor/128x128/apps/in.palera.palera1n.png new file mode 100644 index 0000000..5434f98 Binary files /dev/null and b/resources/icons/hicolor/128x128/apps/in.palera.palera1n.png differ diff --git a/resources/icons/hicolor/256x256/apps/in.palera.palera1n.png b/resources/icons/hicolor/256x256/apps/in.palera.palera1n.png new file mode 100644 index 0000000..82c86f3 Binary files /dev/null and b/resources/icons/hicolor/256x256/apps/in.palera.palera1n.png differ diff --git a/resources/icons/hicolor/512x512/apps/in.palera.palera1n.png b/resources/icons/hicolor/512x512/apps/in.palera.palera1n.png new file mode 100644 index 0000000..3ac5e09 Binary files /dev/null and b/resources/icons/hicolor/512x512/apps/in.palera.palera1n.png differ diff --git a/resources/icons/hicolor/64x64/apps/in.palera.palera1n.png b/resources/icons/hicolor/64x64/apps/in.palera.palera1n.png new file mode 100644 index 0000000..6dae3f6 Binary files /dev/null and b/resources/icons/hicolor/64x64/apps/in.palera.palera1n.png differ diff --git a/resources/in.palera.palera1n.desktop b/resources/in.palera.palera1n.desktop new file mode 100644 index 0000000..2369503 --- /dev/null +++ b/resources/in.palera.palera1n.desktop @@ -0,0 +1,10 @@ +[Desktop Entry] +Version=1.0 +Type=Application +Name=palera1n +Comment=Semi-tethered jailbreak for iOS 15+ +Categories=Utility; +Icon=in.palera.palera1n +Exec=palera1n +Terminal=false +StartupWMClass=in.palera.palera1n diff --git a/src/events/device_info.hpp b/src/events/device_info.hpp index 077d8fc..250309d 100644 --- a/src/events/device_info.hpp +++ b/src/events/device_info.hpp @@ -27,8 +27,8 @@ #if defined(WITH_GUI) || defined(WITH_TUI) -#ifndef MAIN__DEVICE_INFO_H -#define MAIN__DEVICE_INFO_H +#ifndef P1__DEVICE_INFO_HPP +#define P1__DEVICE_INFO_HPP // stolen from irecovery, I dont think an array // of devices can be copyrighted? @@ -382,6 +382,6 @@ static struct irecv_device irecv_devices[] = { void get_recovery_info(char *sn, const char **ecid, const char **product_model, const char **product_name); void get_name_from_product_type(const char *product_type, const char **name); -#endif // MAIN__DEVICE_INFO_H +#endif // P1__DEVICE_INFO_HPP #endif // WITH_GUI || WITH_TUI diff --git a/src/events/event.hpp b/src/events/event.hpp index 9fd77f4..53b9313 100644 --- a/src/events/event.hpp +++ b/src/events/event.hpp @@ -27,8 +27,8 @@ #if defined(WITH_GUI) || defined(WITH_TUI) -#ifndef EVENT_H -#define EVENT_H +#ifndef P1__EVENT_HPP +#define P1__EVENT_HPP #include #include @@ -69,6 +69,6 @@ void ensure_device_event_system_started(); bool enter_recovery(); void exit_recovery(); -#endif // EVENT_H +#endif // P1__EVENT_HPP #endif // WITH_GUI || WITH_TUI diff --git a/src/events/ra1ncovery/hotplug.hpp b/src/events/ra1ncovery/hotplug.hpp index 1182894..3aecb98 100644 --- a/src/events/ra1ncovery/hotplug.hpp +++ b/src/events/ra1ncovery/hotplug.hpp @@ -27,8 +27,8 @@ #if defined(WITH_GUI) || defined(WITH_TUI) -#ifndef MAIN__HOTPLUG_HPP -#define MAIN__HOTPLUG_HPP +#ifndef P1__HOTPLUG_HPP +#define P1__HOTPLUG_HPP #include #include @@ -79,6 +79,6 @@ void exit_recovery(hotplug_handle_t handle); } #endif -#endif // MAIN__HOTPLUG_HPP +#endif // P1__HOTPLUG_HPP #endif // WITH_GUI || WITH_TUI diff --git a/src/exploit.h b/src/exploit.h index 7d5fd32..15d5468 100644 --- a/src/exploit.h +++ b/src/exploit.h @@ -25,8 +25,8 @@ * */ -#ifndef RUN_H -#define RUN_H +#ifndef P1__EXPLOIT_H +#define P1__EXPLOIT_H #include @@ -60,4 +60,4 @@ int exploit(int *stage); } #endif -#endif // RUN_H +#endif // P1__EXPLOIT_H diff --git a/src/globals.h b/src/globals.h index 774d8ed..07fa022 100644 --- a/src/globals.h +++ b/src/globals.h @@ -25,8 +25,8 @@ * */ -#ifndef GLOBALS_H -#define GLOBALS_H +#ifndef P1__GLOBALS_H +#define P1__GLOBALS_H #include #include @@ -59,4 +59,4 @@ bool override_payload_from_file(const char *path, payload_t *out); } #endif -#endif // GLOBALS_H +#endif // P1__GLOBALS_H diff --git a/src/pongo_helper.h b/src/pongo_helper.h index 5872c94..521b78f 100644 --- a/src/pongo_helper.h +++ b/src/pongo_helper.h @@ -25,8 +25,8 @@ * */ -#ifndef USB_PONGO_H -#define USB_PONGO_H +#ifndef P1__PONGO_HELPER_H +#define P1__PONGO_HELPER_H #include #include @@ -49,4 +49,4 @@ typedef checkm8_err_t p1_checkm8_err_t; p1_checkm8_err_t send_compressed_pongo(p1_usb_handle_t *handle, const uint8_t *pongo_bin, const size_t pongo_bin_length); p1_checkm8_err_t send_full_pongo_jailbreak(p1_usb_handle_t *handle); -#endif // USB_PONGO_H +#endif // P1__PONGO_HELPER_H diff --git a/src/sequence.hpp b/src/sequence.hpp index ff6216d..34ed2b6 100644 --- a/src/sequence.hpp +++ b/src/sequence.hpp @@ -27,8 +27,8 @@ #if defined(WITH_GUI) || defined(WITH_TUI) -#ifndef SEQUENCE_H -#define SEQUENCE_H +#ifndef P1__SEQUENCE_HPP +#define P1__SEQUENCE_HPP #include #include @@ -64,6 +64,6 @@ DfuSequence ParseSequence(const std::string& deviceKey); bool SequenceIsSupported(const DfuSequence* seq); bool SequenceRequiresCLI(const DfuSequence* seq); -#endif // SEQUENCE_H +#endif // P1__SEQUENCE_HPP #endif // WITH_GUI || WITH_TUI diff --git a/src/tui/Tui.hpp b/src/tui/Tui.hpp index 0f60b64..1ce306b 100644 --- a/src/tui/Tui.hpp +++ b/src/tui/Tui.hpp @@ -27,8 +27,8 @@ #ifdef WITH_TUI -#ifndef TUI_HPP -#define TUI_HPP +#ifndef P1__TUI_HPP +#define P1__TUI_HPP #include #include @@ -93,6 +93,6 @@ private: void ui_run(void); void update_tui_device_state(const DeviceState* new_state); -#endif // TUI_HPP +#endif // P1__TUI_HPP #endif // WITH_TUI diff --git a/src/tui/TuiBranding.hpp b/src/tui/TuiBranding.hpp index 072a150..7fc276a 100644 --- a/src/tui/TuiBranding.hpp +++ b/src/tui/TuiBranding.hpp @@ -27,11 +27,11 @@ #ifdef WITH_TUI -#ifndef TUI_BRANDING_HPP -#define TUI_BRANDING_HPP +#ifndef P1__TUI_BRANDING_HPP +#define P1__TUI_BRANDING_HPP void draw_tui_sidebar_branding(int y, int x, int width); -#endif // TUI_BRANDING_HPP +#endif // P1__TUI_BRANDING_HPP #endif // WITH_TUI diff --git a/src/tui/TuiDfuArt.hpp b/src/tui/TuiDfuArt.hpp index 71991d8..0ba9761 100644 --- a/src/tui/TuiDfuArt.hpp +++ b/src/tui/TuiDfuArt.hpp @@ -27,8 +27,8 @@ #ifdef WITH_TUI -#ifndef TUI_DFU_ART_HPP -#define TUI_DFU_ART_HPP +#ifndef P1__TUI_DFU_ART_HPP +#define P1__TUI_DFU_ART_HPP #include @@ -43,6 +43,6 @@ struct DfuAsciiPreview { const DfuAsciiPreview* find_dfu_ascii_preview(const std::string& imageName); void draw_dfu_ascii_preview(const DfuAsciiPreview& preview, int sx, int sy); -#endif // TUI_DFU_ART_HPP +#endif // P1__TUI_DFU_ART_HPP #endif // WITH_TUI diff --git a/src/tui/TuiDfuPanel.hpp b/src/tui/TuiDfuPanel.hpp index 843e1e9..8403279 100644 --- a/src/tui/TuiDfuPanel.hpp +++ b/src/tui/TuiDfuPanel.hpp @@ -27,8 +27,8 @@ #ifdef WITH_TUI -#ifndef TUI_DFU_PANEL_HPP -#define TUI_DFU_PANEL_HPP +#ifndef P1__TUI_DFU_PANEL_HPP +#define P1__TUI_DFU_PANEL_HPP #include "TuiPanel.hpp" #include "../sequence.hpp" @@ -73,6 +73,6 @@ private: std::chrono::steady_clock::time_point m_last_tick; }; -#endif // TUI_DFU_PANEL_HPP +#endif // P1__TUI_DFU_PANEL_HPP #endif // WITH_TUI diff --git a/src/tui/TuiExploitPanel.hpp b/src/tui/TuiExploitPanel.hpp index 966f784..8cbddca 100644 --- a/src/tui/TuiExploitPanel.hpp +++ b/src/tui/TuiExploitPanel.hpp @@ -27,8 +27,8 @@ #ifdef WITH_TUI -#ifndef TUI_EXPLOIT_PANEL_HPP -#define TUI_EXPLOIT_PANEL_HPP +#ifndef P1__TUI_EXPLOIT_PANEL_HPP +#define P1__TUI_EXPLOIT_PANEL_HPP #include "TuiPanel.hpp" @@ -60,6 +60,6 @@ private: std::atomic m_is_exploiting{false}; }; -#endif // TUI_EXPLOIT_PANEL_HPP +#endif // P1__TUI_EXPLOIT_PANEL_HPP #endif // WITH_TUI diff --git a/src/tui/TuiMainPanel.hpp b/src/tui/TuiMainPanel.hpp index 0435aee..8b27919 100644 --- a/src/tui/TuiMainPanel.hpp +++ b/src/tui/TuiMainPanel.hpp @@ -27,8 +27,8 @@ #ifdef WITH_TUI -#ifndef TUI_MAIN_PANEL_HPP -#define TUI_MAIN_PANEL_HPP +#ifndef P1__TUI_MAIN_PANEL_HPP +#define P1__TUI_MAIN_PANEL_HPP #include "TuiPanel.hpp" @@ -47,6 +47,6 @@ public: const char** get_buttons() const override; }; -#endif // TUI_MAIN_PANEL_HPP +#endif // P1__TUI_MAIN_PANEL_HPP #endif // WITH_TUI diff --git a/src/tui/TuiPanel.hpp b/src/tui/TuiPanel.hpp index b688f74..faf5b6e 100644 --- a/src/tui/TuiPanel.hpp +++ b/src/tui/TuiPanel.hpp @@ -27,8 +27,8 @@ #ifdef WITH_TUI -#ifndef TUI_PANEL_HPP -#define TUI_PANEL_HPP +#ifndef P1__TUI_PANEL_HPP +#define P1__TUI_PANEL_HPP #include @@ -71,6 +71,6 @@ private: TuiFrame* m_frame = nullptr; }; -#endif // TUI_PANEL_HPP +#endif // P1__TUI_PANEL_HPP #endif // WITH_TUI diff --git a/src/tui/TuiRecoveryPanel.hpp b/src/tui/TuiRecoveryPanel.hpp index 7719fd9..c7a05ee 100644 --- a/src/tui/TuiRecoveryPanel.hpp +++ b/src/tui/TuiRecoveryPanel.hpp @@ -27,8 +27,8 @@ #ifdef WITH_TUI -#ifndef TUI_RECOVERY_PANEL_HPP -#define TUI_RECOVERY_PANEL_HPP +#ifndef P1__TUI_RECOVERY_PANEL_HPP +#define P1__TUI_RECOVERY_PANEL_HPP #include "TuiPanel.hpp" @@ -61,6 +61,6 @@ private: bool m_buttons_disabled; }; -#endif // TUI_RECOVERY_PANEL_HPP +#endif // P1__TUI_RECOVERY_PANEL_HPP #endif // WITH_TUI diff --git a/src/tui/TuiSettingsPanel.hpp b/src/tui/TuiSettingsPanel.hpp index 77d9b5f..6ff50e6 100644 --- a/src/tui/TuiSettingsPanel.hpp +++ b/src/tui/TuiSettingsPanel.hpp @@ -27,8 +27,8 @@ #ifdef WITH_TUI -#ifndef TUI_SETTINGS_PANEL_HPP -#define TUI_SETTINGS_PANEL_HPP +#ifndef P1__TUI_SETTINGS_PANEL_HPP +#define P1__TUI_SETTINGS_PANEL_HPP #include "TuiPanel.hpp" @@ -50,6 +50,6 @@ private: void edit_boot_args(int start_y, int start_x); }; -#endif // TUI_SETTINGS_PANEL_HPP +#endif // P1__TUI_SETTINGS_PANEL_HPP #endif // WITH_TUI diff --git a/src/tui/TuiText.hpp b/src/tui/TuiText.hpp index 628b142..1131086 100644 --- a/src/tui/TuiText.hpp +++ b/src/tui/TuiText.hpp @@ -27,8 +27,8 @@ #ifdef WITH_TUI -#ifndef TUI_TEXT_HPP -#define TUI_TEXT_HPP +#ifndef P1__TUI_TEXT_HPP +#define P1__TUI_TEXT_HPP #include @@ -105,6 +105,6 @@ inline int draw_wrapped_text(int y, int x, int width, const std::string& text, i } // namespace tui_text -#endif // TUI_TEXT_HPP +#endif // P1__TUI_TEXT_HPP #endif // WITH_TUI diff --git a/src/udevhelper.c b/src/udevhelper.c new file mode 100644 index 0000000..66b4844 --- /dev/null +++ b/src/udevhelper.c @@ -0,0 +1,81 @@ +/* + * palera1n - https://palera.in + * + * Copyright (C) 2026 palera1n team + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#if defined(__linux__) + +#include "udevhelper.h" + +#include +#include +#include +#include // waitpid +#include // chmod + +#include "gen/embedded/add_udev_rules.h" + +int udev_rules_exist(void) +{ + return access("/etc/udev/rules.d/turdusra1n.rules", F_OK) == 0; +} + +int add_udev_rules(void) +{ + FILE *f = fopen("/tmp/udevhelper.sh", "wb"); + if (!f) + return 1; + + fwrite( + embedded_add_udev_rules_sh, + 1, + embedded_add_udev_rules_sh_len, + f + ); + fclose(f); + + chmod("/tmp/udevhelper.sh", 0700); + + pid_t pid = fork(); + + if (pid < 0) { + unlink("/tmp/udevhelper.sh"); + return 1; + } + + if (pid == 0) { + execlp("pkexec", "pkexec", "/tmp/udevhelper.sh", (char *)NULL); + exit(1); + } + + int status; + waitpid(pid, &status, 0); + + unlink("/tmp/udevhelper.sh"); + + return WIFEXITED(status) ? WEXITSTATUS(status) : 1; +} + +#endif // defined(__linux__) diff --git a/src/udevhelper.h b/src/udevhelper.h new file mode 100644 index 0000000..3168984 --- /dev/null +++ b/src/udevhelper.h @@ -0,0 +1,48 @@ +/* + * palera1n - https://palera.in + * + * Copyright (C) 2026 palera1n team + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#ifndef P1__UDEVHELPER_H +#define P1__GLOBALS_H + +#if defined(__linux__) + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int udev_rules_exist(void); +int add_udev_rules(void); + +#ifdef __cplusplus +} +#endif + +#endif // defined(__linux__) + +#endif // P1__GLOBALS_H diff --git a/src/wx/AppFrame.cpp b/src/wx/AppFrame.cpp index 2c8d017..18b558c 100644 --- a/src/wx/AppFrame.cpp +++ b/src/wx/AppFrame.cpp @@ -31,6 +31,9 @@ #include #include "../globals.h" +#if defined(WITH_GUI) && defined(__linux__) +# include "../udevhelper.h" +#endif #include "../events/event.hpp" wxDEFINE_EVENT(EVT_DEVICE_STATE_UPDATE, wxCommandEvent); @@ -106,6 +109,36 @@ void MainFrame::ShowMain() m_dfu->Hide(); m_exploit->Hide(); Layout(); + + // check udev rules + #if defined(WITH_GUI) && defined(__linux__) + + if (!udev_rules_exist()) { + int result = wxMessageBox( + "USB permissions need to be configured before exploiting.\n\n" + "This will install the required udev rules so palera1n " + "can communicate with your device over USB in DFU.\n\n" + "Otherwise, we may not be able to jailbreak your device.", + "Set Up USB Permissions", + wxYES_NO | wxICON_INFORMATION, + this + ); + + if (result != wxYES) + return; + + if (add_udev_rules() != 0) { + wxMessageBox( + "Failed to configure USB permissions.", + "Error", + wxOK | wxICON_ERROR, + this + ); + return; + } + } + + #endif } void MainFrame::ShowSettings() diff --git a/src/wx/AppFrame.hpp b/src/wx/AppFrame.hpp index 404a174..4014263 100644 --- a/src/wx/AppFrame.hpp +++ b/src/wx/AppFrame.hpp @@ -25,8 +25,8 @@ * */ -#ifndef APPFRAME_H -#define APPFRAME_H +#ifndef P1__APP_FRAME_HPP +#define P1__APP_FRAME_HPP #ifdef WITH_GUI @@ -77,4 +77,4 @@ public: #endif // WITH_GUI -#endif // APPFRAME_H +#endif // P1__APP_FRAME_HPP diff --git a/src/wx/DevicePanel.hpp b/src/wx/DevicePanel.hpp index 8c3d316..38ff99c 100644 --- a/src/wx/DevicePanel.hpp +++ b/src/wx/DevicePanel.hpp @@ -25,8 +25,8 @@ * */ -#ifndef DEVICEPANEL_H -#define DEVICEPANEL_H +#ifndef P1__DEVICE_PANEL_HPP +#define P1__DEVICE_PANEL_HPP #include #include "../events/event.hpp" @@ -65,4 +65,4 @@ private: DeviceState m_deviceState; }; -#endif // DEVICEPANEL_H +#endif // P1__DEVICE_PANEL_HPP diff --git a/src/wx/DfuPanel.hpp b/src/wx/DfuPanel.hpp index 4b603d4..b2dac60 100644 --- a/src/wx/DfuPanel.hpp +++ b/src/wx/DfuPanel.hpp @@ -25,8 +25,8 @@ * */ -#ifndef DFUPANEL_H -#define DFUPANEL_H +#ifndef P1__DFU_PANEL_HPP +#define P1__DFU_PANEL_HPP #ifdef WITH_GUI @@ -73,4 +73,4 @@ private: #endif // WITH_GUI -#endif // DFUPANEL_H +#endif // P1__DFU_PANEL_HPP diff --git a/src/wx/ExploitPanel.hpp b/src/wx/ExploitPanel.hpp index 33962b5..b7a4ab7 100644 --- a/src/wx/ExploitPanel.hpp +++ b/src/wx/ExploitPanel.hpp @@ -25,8 +25,8 @@ * */ -#ifndef EXPLOITPANEL_HPP -#define EXPLOITPANEL_HPP +#ifndef P1__EXPLOIT_PANEL_HPP +#define P1__EXPLOIT_PANEL_HPP #ifdef WITH_GUI @@ -49,4 +49,4 @@ private: #endif // WITH_GUI -#endif // EXPLOITPANEL_HPP +#endif // P1__EXPLOIT_PANEL_HPP diff --git a/src/wx/MainPanel.hpp b/src/wx/MainPanel.hpp index 8eb4be8..ba38300 100644 --- a/src/wx/MainPanel.hpp +++ b/src/wx/MainPanel.hpp @@ -25,8 +25,8 @@ * */ -#ifndef MAINPANEL_H -#define MAINPANEL_H +#ifndef P1__MAIN_PANEL_HPP +#define P1__MAIN_PANEL_HPP #ifdef WITH_GUI @@ -48,4 +48,4 @@ private: #endif // WITH_GUI -#endif // MAINPANEL_H +#endif // P1__MAIN_PANEL_HPP diff --git a/src/wx/RecoveryPanel.hpp b/src/wx/RecoveryPanel.hpp index 3ac2ff6..c1b99fd 100644 --- a/src/wx/RecoveryPanel.hpp +++ b/src/wx/RecoveryPanel.hpp @@ -25,8 +25,8 @@ * */ -#ifndef RECOVERYPANEL_H -#define RECOVERYPANEL_H +#ifndef P1__RECOVERY_PANEL_HPP +#define P1__RECOVERY_PANEL_HPP #ifdef WITH_GUI @@ -53,4 +53,4 @@ private: #endif // WITH_GUI -#endif // RECOVERYPANEL_H +#endif // P1__RECOVERY_PANEL_HPP diff --git a/src/wx/SettingsPanel.hpp b/src/wx/SettingsPanel.hpp index 3078bed..23a82dc 100644 --- a/src/wx/SettingsPanel.hpp +++ b/src/wx/SettingsPanel.hpp @@ -25,8 +25,8 @@ * */ -#ifndef SETTINGSPANEL_H -#define SETTINGSPANEL_H +#ifndef P1__SETTINGS_PANEL_HPP +#define P1__SETTINGS_PANEL_HPP #ifdef WITH_GUI @@ -42,4 +42,4 @@ public: #endif // WITH_GUI -#endif // SETTINGSPANEL_H +#endif // P1__SETTINGS_PANEL_HPP