From 1c27d4a73d2d2ffa43b0d59c5a2cb727920e2c27 Mon Sep 17 00:00:00 2001 From: bruvzg <7645683+bruvzg@users.noreply.github.com> Date: Wed, 3 Mar 2021 12:40:38 +0200 Subject: [PATCH] [macOS] Add entitlements config and export template `dylib` signing to the export. --- platform/osx/export/export.cpp | 171 +++++++++++++++++++++++++++++++-- 1 file changed, 163 insertions(+), 8 deletions(-) diff --git a/platform/osx/export/export.cpp b/platform/osx/export/export.cpp index acefd1db651..7448fb30279 100644 --- a/platform/osx/export/export.cpp +++ b/platform/osx/export/export.cpp @@ -56,7 +56,7 @@ class EditorExportPlatformOSX : public EditorExportPlatform { void _fix_plist(const Ref &p_preset, Vector &plist, const String &p_binary); void _make_icon(const Ref &p_icon, Vector &p_data); - Error _code_sign(const Ref &p_preset, const String &p_path); + Error _code_sign(const Ref &p_preset, const String &p_path, const String &p_ent_path); Error _create_dmg(const String &p_dmg_path, const String &p_pkg_name, const String &p_app_path_name); void _zip_folder_recursive(zipFile &p_zip, const String &p_root_path, const String &p_folder, const String &p_pkg_name); @@ -139,7 +139,30 @@ void EditorExportPlatformOSX::get_export_options(List *r_options) r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/identity", PROPERTY_HINT_PLACEHOLDER_TEXT, "Type: Name (ID)"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/timestamp"), true)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/hardened_runtime"), true)); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/entitlements", PROPERTY_HINT_GLOBAL_FILE, "*.plist"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/entitlements/custom_file", PROPERTY_HINT_GLOBAL_FILE, "*.plist"), "")); + + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/allow_jit_code_execution"), false)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/allow_unsigned_executable_memory"), false)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/allow_dyld_environment_variables"), false)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/disable_library_validation"), false)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/audio_input"), false)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/camera"), false)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/location"), false)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/address_book"), false)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/calendars"), false)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/photos_library"), false)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/apple_events"), false)); + + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/app_sandbox/enabled"), false)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/app_sandbox/network_server"), false)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/app_sandbox/network_client"), false)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/app_sandbox/device_usb"), false)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/app_sandbox/device_bluetooth"), false)); + r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/entitlements/app_sandbox/files_downloads", PROPERTY_HINT_ENUM, "No,Read-only,Read-write"), 0)); + r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/entitlements/app_sandbox/files_pictures", PROPERTY_HINT_ENUM, "No,Read-only,Read-write"), 0)); + r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/entitlements/app_sandbox/files_music", PROPERTY_HINT_ENUM, "No,Read-only,Read-write"), 0)); + r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/entitlements/app_sandbox/files_movies", PROPERTY_HINT_ENUM, "No,Read-only,Read-write"), 0)); + r_options->push_back(ExportOption(PropertyInfo(Variant::POOL_STRING_ARRAY, "codesign/custom_options"), PoolStringArray())); #endif @@ -370,7 +393,7 @@ void EditorExportPlatformOSX::_fix_plist(const Ref &p_preset - and then wrap it up in a DMG **/ -Error EditorExportPlatformOSX::_code_sign(const Ref &p_preset, const String &p_path) { +Error EditorExportPlatformOSX::_code_sign(const Ref &p_preset, const String &p_path, const String &p_ent_path) { #ifdef OSX_ENABLED List args; @@ -382,9 +405,9 @@ Error EditorExportPlatformOSX::_code_sign(const Ref &p_prese args.push_back("runtime"); } - if ((p_preset->get("codesign/entitlements") != "") && (p_path.get_extension() != "dmg")) { + if (p_path.get_extension() != "dmg") { args.push_back("--entitlements"); - args.push_back(p_preset->get("codesign/entitlements")); + args.push_back(p_ent_path); } PoolStringArray user_args = p_preset->get("codesign/custom_options"); @@ -539,6 +562,7 @@ Error EditorExportPlatformOSX::export_project(const Ref &p_p // Now process our template. bool found_binary = false; int total_size = 0; + Vector dylibs_found; while (ret == UNZ_OK && err == OK) { bool is_execute = false; @@ -620,6 +644,10 @@ Error EditorExportPlatformOSX::export_project(const Ref &p_p file = file.replace("/data.mono.osx.64.release/", "/data_" + pkg_name + "/"); } + if (file.ends_with(".dylib")) { + dylibs_found.push_back(file); + } + print_line("ADDING: " + file + " size: " + itos(data.size())); total_size += data.size(); @@ -667,22 +695,149 @@ Error EditorExportPlatformOSX::export_project(const Ref &p_p // See if we can code sign our new package. bool sign_enabled = p_preset->get("codesign/enable"); + String ent_path = p_preset->get("codesign/entitlements/custom_file"); + if (sign_enabled && (ent_path == "")) { + ent_path = EditorSettings::get_singleton()->get_cache_dir().plus_file(pkg_name + ".entitlements"); + + FileAccess *ent_f = FileAccess::open(ent_path, FileAccess::WRITE); + if (ent_f) { + ent_f->store_line(""); + ent_f->store_line(""); + ent_f->store_line(""); + ent_f->store_line(""); + if ((bool)p_preset->get("codesign/entitlements/allow_jit_code_execution")) { + ent_f->store_line("com.apple.security.cs.allow-jit"); + ent_f->store_line(""); + } + if ((bool)p_preset->get("codesign/entitlements/allow_unsigned_executable_memory")) { + ent_f->store_line("com.apple.security.cs.allow-unsigned-executable-memory"); + ent_f->store_line(""); + } + if ((bool)p_preset->get("codesign/entitlements/allow_dyld_environment_variables")) { + ent_f->store_line("com.apple.security.cs.allow-dyld-environment-variables"); + ent_f->store_line(""); + } + if ((bool)p_preset->get("codesign/entitlements/disable_library_validation")) { + ent_f->store_line("com.apple.security.cs.disable-library-validation"); + ent_f->store_line(""); + } + if ((bool)p_preset->get("codesign/entitlements/audio_input")) { + ent_f->store_line("com.apple.security.device.audio-input"); + ent_f->store_line(""); + } + if ((bool)p_preset->get("codesign/entitlements/camera")) { + ent_f->store_line("com.apple.security.device.camera"); + ent_f->store_line(""); + } + if ((bool)p_preset->get("codesign/entitlements/location")) { + ent_f->store_line("com.apple.security.personal-information.location"); + ent_f->store_line(""); + } + if ((bool)p_preset->get("codesign/entitlements/address_book")) { + ent_f->store_line("com.apple.security.personal-information.addressbook"); + ent_f->store_line(""); + } + if ((bool)p_preset->get("codesign/entitlements/calendars")) { + ent_f->store_line("com.apple.security.personal-information.calendars"); + ent_f->store_line(""); + } + if ((bool)p_preset->get("codesign/entitlements/photos_library")) { + ent_f->store_line("com.apple.security.personal-information.photos-library"); + ent_f->store_line(""); + } + if ((bool)p_preset->get("codesign/entitlements/apple_events")) { + ent_f->store_line("com.apple.security.automation.apple-events"); + ent_f->store_line(""); + } + + if ((bool)p_preset->get("codesign/entitlements/app_sandbox/enabled")) { + ent_f->store_line("com.apple.security.app-sandbox"); + ent_f->store_line(""); + + if ((bool)p_preset->get("codesign/entitlements/app_sandbox/network_server")) { + ent_f->store_line("com.apple.security.network.server"); + ent_f->store_line(""); + } + if ((bool)p_preset->get("codesign/entitlements/app_sandbox/network_client")) { + ent_f->store_line("com.apple.security.network.client"); + ent_f->store_line(""); + } + if ((bool)p_preset->get("codesign/entitlements/app_sandbox/device_usb")) { + ent_f->store_line("com.apple.security.device.usb"); + ent_f->store_line(""); + } + if ((bool)p_preset->get("codesign/entitlements/app_sandbox/device_bluetooth")) { + ent_f->store_line("com.apple.security.device.bluetooth"); + ent_f->store_line(""); + } + if ((int)p_preset->get("codesign/entitlements/app_sandbox/files_downloads") == 1) { + ent_f->store_line("com.apple.security.files.downloads.read-only"); + ent_f->store_line(""); + } + if ((int)p_preset->get("codesign/entitlements/app_sandbox/files_downloads") == 2) { + ent_f->store_line("com.apple.security.files.downloads.read-write"); + ent_f->store_line(""); + } + if ((int)p_preset->get("codesign/entitlements/app_sandbox/files_pictures") == 1) { + ent_f->store_line("com.apple.security.files.pictures.read-only"); + ent_f->store_line(""); + } + if ((int)p_preset->get("codesign/entitlements/app_sandbox/files_pictures") == 2) { + ent_f->store_line("com.apple.security.files.pictures.read-write"); + ent_f->store_line(""); + } + if ((int)p_preset->get("codesign/entitlements/app_sandbox/files_music") == 1) { + ent_f->store_line("com.apple.security.files.music.read-only"); + ent_f->store_line(""); + } + if ((int)p_preset->get("codesign/entitlements/app_sandbox/files_music") == 2) { + ent_f->store_line("com.apple.security.files.music.read-write"); + ent_f->store_line(""); + } + if ((int)p_preset->get("codesign/entitlements/app_sandbox/files_movies") == 1) { + ent_f->store_line("com.apple.security.files.movies.read-only"); + ent_f->store_line(""); + } + if ((int)p_preset->get("codesign/entitlements/app_sandbox/files_movies") == 2) { + ent_f->store_line("com.apple.security.files.movies.read-write"); + ent_f->store_line(""); + } + } + + ent_f->store_line(""); + ent_f->store_line(""); + + ent_f->close(); + memdelete(ent_f); + } else { + err = ERR_CANT_CREATE; + } + } + if (err == OK) { DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); for (int i = 0; i < shared_objects.size(); i++) { err = da->copy(shared_objects[i].path, tmp_app_path_name + "/Contents/Frameworks/" + shared_objects[i].path.get_file()); if (err == OK && sign_enabled) { - err = _code_sign(p_preset, tmp_app_path_name + "/Contents/Frameworks/" + shared_objects[i].path.get_file()); + err = _code_sign(p_preset, tmp_app_path_name + "/Contents/Frameworks/" + shared_objects[i].path.get_file(), ent_path); } } memdelete(da); } + if (sign_enabled) { + for (int i = 0; i < dylibs_found.size(); i++) { + if (err == OK) { + err = _code_sign(p_preset, tmp_app_path_name + "/" + dylibs_found[i], ent_path); + } + } + } + if (err == OK && sign_enabled) { if (ep.step("Code signing bundle", 2)) { return ERR_SKIP; } - err = _code_sign(p_preset, tmp_app_path_name + "/Contents/MacOS/" + pkg_name); + err = _code_sign(p_preset, tmp_app_path_name + "/Contents/MacOS/" + pkg_name, ent_path); } if (export_format == "dmg") { @@ -698,7 +853,7 @@ Error EditorExportPlatformOSX::export_project(const Ref &p_p if (ep.step("Code signing DMG", 3)) { return ERR_SKIP; } - err = _code_sign(p_preset, p_path); + err = _code_sign(p_preset, p_path, ent_path); } } else { // Create ZIP.