Repo // Sandbox entitlements and hardened runtime.
This commit is contained in:
parent
f300305f85
commit
bc0c26891a
|
@ -13,12 +13,14 @@ import Cocoa
|
|||
private let kTargetBin = "vChewing"
|
||||
private let kTargetType = "app"
|
||||
private let kTargetBundle = "vChewing.app"
|
||||
private let kTargetBundleWithComponents = "Library/Input%20Methods/vChewing.app"
|
||||
|
||||
private let urlDestinationPartial = FileManager.default.urls(
|
||||
for: .inputMethodsDirectory, in: .userDomainMask
|
||||
)[0]
|
||||
private let urlTargetPartial = urlDestinationPartial.appendingPathComponent(kTargetBundle)
|
||||
private let urlTargetFullBinPartial = urlTargetPartial.appendingPathComponent("Contents/MacOS/")
|
||||
private let realHomeDir = URL(
|
||||
fileURLWithFileSystemRepresentation: getpwuid(getuid()).pointee.pw_dir, isDirectory: true, relativeTo: nil
|
||||
)
|
||||
private let urlDestinationPartial = realHomeDir.appendingPathComponent("Library/Input Methods")
|
||||
private let urlTargetPartial = realHomeDir.appendingPathComponent(kTargetBundleWithComponents)
|
||||
private let urlTargetFullBinPartial = urlTargetPartial.appendingPathComponent("Contents/MacOS")
|
||||
.appendingPathComponent(kTargetBin)
|
||||
|
||||
private let kDestinationPartial = urlDestinationPartial.path
|
||||
|
@ -93,9 +95,9 @@ class AppDelegate: NSWindowController, NSApplicationDelegate {
|
|||
window?.standardWindowButton(.zoomButton)?.isHidden = true
|
||||
|
||||
if FileManager.default.fileExists(
|
||||
atPath: (kTargetPartialPath as NSString).expandingTildeInPath)
|
||||
atPath: kTargetPartialPath)
|
||||
{
|
||||
let currentBundle = Bundle(path: (kTargetPartialPath as NSString).expandingTildeInPath)
|
||||
let currentBundle = Bundle(path: kTargetPartialPath)
|
||||
let shortVersion =
|
||||
currentBundle?.infoDictionary?["CFBundleShortVersionString"] as? String
|
||||
let currentVersion =
|
||||
|
@ -136,15 +138,12 @@ class AppDelegate: NSWindowController, NSApplicationDelegate {
|
|||
}
|
||||
|
||||
func removeThenInstallInputMethod() {
|
||||
if FileManager.default.fileExists(
|
||||
atPath: (kTargetPartialPath as NSString).expandingTildeInPath)
|
||||
== false
|
||||
{
|
||||
installInputMethod(
|
||||
previousExists: false, previousVersionNotFullyDeactivatedWarning: false
|
||||
)
|
||||
return
|
||||
}
|
||||
// if !FileManager.default.fileExists(atPath: kTargetPartialPath) {
|
||||
// installInputMethod(
|
||||
// previousExists: false, previousVersionNotFullyDeactivatedWarning: false
|
||||
// )
|
||||
// return
|
||||
// }
|
||||
|
||||
let shouldWaitForTranslocationRemoval =
|
||||
isAppBundleTranslocated(atPath: kTargetPartialPath)
|
||||
|
@ -152,7 +151,7 @@ class AppDelegate: NSWindowController, NSApplicationDelegate {
|
|||
|
||||
// 將既存輸入法扔到垃圾桶內
|
||||
do {
|
||||
let sourceDir = (kDestinationPartial as NSString).expandingTildeInPath
|
||||
let sourceDir = kDestinationPartial
|
||||
let fileManager = FileManager.default
|
||||
let fileURLString = String(format: "%@/%@", sourceDir, kTargetBundle)
|
||||
let fileURL = URL(fileURLWithPath: fileURLString)
|
||||
|
@ -216,8 +215,9 @@ class AppDelegate: NSWindowController, NSApplicationDelegate {
|
|||
}
|
||||
let cpTask = Process()
|
||||
cpTask.launchPath = "/bin/cp"
|
||||
print(kDestinationPartial)
|
||||
cpTask.arguments = [
|
||||
"-R", targetBundle, (kDestinationPartial as NSString).expandingTildeInPath,
|
||||
"-R", targetBundle, kDestinationPartial,
|
||||
]
|
||||
cpTask.launch()
|
||||
cpTask.waitUntilExit()
|
||||
|
@ -231,7 +231,11 @@ class AppDelegate: NSWindowController, NSApplicationDelegate {
|
|||
endAppWithDelay()
|
||||
}
|
||||
|
||||
guard let imeBundle = Bundle(path: (kTargetPartialPath as NSString).expandingTildeInPath),
|
||||
let imeURLInstalled = realHomeDir.appendingPathComponent("Library/Input Methods/vChewing.app")
|
||||
|
||||
_ = try? shell("/usr/bin/xattr -drs com.apple.quarantine \(kTargetPartialPath)")
|
||||
|
||||
guard let imeBundle = Bundle(url: imeURLInstalled),
|
||||
let imeIdentifier = imeBundle.bundleIdentifier
|
||||
else {
|
||||
endAppWithDelay()
|
||||
|
@ -343,6 +347,30 @@ class AppDelegate: NSWindowController, NSApplicationDelegate {
|
|||
NSApp.terminate(self)
|
||||
}
|
||||
|
||||
private func shell(_ command: String) throws -> String {
|
||||
let task = Process()
|
||||
let pipe = Pipe()
|
||||
|
||||
task.standardOutput = pipe
|
||||
task.standardError = pipe
|
||||
task.arguments = ["-c", command]
|
||||
if #available(macOS 10.13, *) {
|
||||
task.executableURL = URL(fileURLWithPath: "/bin/zsh")
|
||||
} else {
|
||||
task.launchPath = "/bin/zsh"
|
||||
}
|
||||
task.standardInput = nil
|
||||
|
||||
if #available(macOS 10.13, *) {
|
||||
try task.run()
|
||||
}
|
||||
|
||||
let data = pipe.fileHandleForReading.readDataToEndOfFile()
|
||||
let output = String(data: data, encoding: .utf8)!
|
||||
|
||||
return output
|
||||
}
|
||||
|
||||
// Determines if an app is translocated by Gatekeeper to a randomized path.
|
||||
// See https://weblog.rogueamoeba.com/2016/06/29/sierra-and-gatekeeper-path-randomization/
|
||||
// Originally written by Zonble Yang in Objective-C (MIT License).
|
||||
|
@ -350,7 +378,7 @@ class AppDelegate: NSWindowController, NSApplicationDelegate {
|
|||
func isAppBundleTranslocated(atPath bundlePath: String) -> Bool {
|
||||
var entryCount = getfsstat(nil, 0, 0)
|
||||
var entries: [statfs] = .init(repeating: .init(), count: Int(entryCount))
|
||||
let absPath = (bundlePath as NSString).expandingTildeInPath.cString(using: .utf8)
|
||||
let absPath = bundlePath.cString(using: .utf8)
|
||||
entryCount = getfsstat(&entries, entryCount * Int32(MemoryLayout<statfs>.stride), MNT_NOWAIT)
|
||||
for entry in entries.prefix(Int(entryCount)) {
|
||||
let isMatch = withUnsafeBytes(of: entry.f_mntfromname) { mntFromName in
|
||||
|
|
|
@ -22,6 +22,9 @@ public enum InputMode: String {
|
|||
public enum IME {
|
||||
static let arrSupportedLocales = ["en", "zh-Hant", "zh-Hans", "ja"]
|
||||
static let dlgOpenPath = NSOpenPanel()
|
||||
public static let realHomeDir = URL(
|
||||
fileURLWithFileSystemRepresentation: getpwuid(getuid()).pointee.pw_dir, isDirectory: true, relativeTo: nil
|
||||
)
|
||||
|
||||
// MARK: - 瀏覽器 Bundle Identifier 關鍵詞匹配黑名單
|
||||
|
||||
|
@ -173,16 +176,23 @@ public enum IME {
|
|||
return -1
|
||||
}
|
||||
|
||||
let kTargetBin = "vChewing"
|
||||
// 自威注音 v2.3.0 開始,沙箱限制了威注音的某些行為,所以該函式不再受理 sudo 模式下的操作。
|
||||
if isSudo {
|
||||
print(
|
||||
"vChewing binary does not support sudo-uninstall since v2.3.0. Please use the bundled uninstall.sh instead.\n\nIf you want to fix the installation (i.e. removing all incorrectly installed files outside of the current user folder), please use the bundled fixinstall.sh instead.\n\nIf you don't know how to proceed, please bring either the uninstall.sh / install.sh or the instruction article https://vchewing.github.io/UNINSTALL.html to Apple Support (support.apple.com) for help. Their senior advisors can understand these uninstall instructions."
|
||||
)
|
||||
return -1
|
||||
}
|
||||
|
||||
let kTargetBundle = "/vChewing.app"
|
||||
let pathLibrary =
|
||||
isSudo
|
||||
? "/Library"
|
||||
: FileManager.default.urls(for: .libraryDirectory, in: .userDomainMask)[0].path
|
||||
: IME.realHomeDir.appendingPathComponent("Library/").path
|
||||
let pathIMELibrary =
|
||||
isSudo
|
||||
? "/Library/Input Methods"
|
||||
: FileManager.default.urls(for: .inputMethodsDirectory, in: .userDomainMask)[0].path
|
||||
: IME.realHomeDir.appendingPathComponent("Library/Input Methods/").path
|
||||
let pathUnitKeyboardLayouts = "/Keyboard Layouts"
|
||||
let arrKeyLayoutFiles = [
|
||||
"/vChewing ETen.keylayout", "/vChewingKeyLayout.bundle", "/vChewing MiTAC.keylayout",
|
||||
|
@ -203,15 +213,13 @@ public enum IME {
|
|||
// 目前暫時無法應對 symbol link 的情況。
|
||||
IME.trashTargetIfExists(mgrLangModel.dataFolderPath(isDefaultFolder: true))
|
||||
IME.trashTargetIfExists(pathLibrary + "/Preferences/" + bundleID + ".plist") // 之後移除 App 偏好設定
|
||||
IME.trashTargetIfExists(pathLibrary + "/Receipts/org.atelierInmu.vChewing.bom") // pkg 垃圾
|
||||
IME.trashTargetIfExists(pathLibrary + "/Receipts/org.atelierInmu.vChewing.plist") // pkg 垃圾
|
||||
}
|
||||
if !IME.trashTargetIfExists(pathIMELibrary + kTargetBundle) { return -1 } // 最後移除 App 自身
|
||||
// 幹掉殘留在記憶體內的執行緒。
|
||||
if selfKill {
|
||||
let killTask = Process()
|
||||
killTask.launchPath = "/usr/bin/killall"
|
||||
killTask.arguments = ["-9", kTargetBin]
|
||||
killTask.launch()
|
||||
killTask.waitUntilExit()
|
||||
NSApplication.shared.terminate(nil)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.bookmarks.app-scope</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.user-selected.read-write</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.client</key>
|
||||
<true/>
|
||||
<key>com.apple.security.temporary-exception.files.home-relative-path.read-write</key>
|
||||
<array>
|
||||
<string>/</string>
|
||||
</array>
|
||||
<key>com.apple.security.temporary-exception.mach-register.global-name</key>
|
||||
<string>org.atelierInmu.inputmethod.vChewing_Connection</string>
|
||||
<key>com.apple.security.temporary-exception.shared-preference.read-only</key>
|
||||
<string>org.atelierInmu.inputmethod.vChewing</string>
|
||||
</dict>
|
||||
</plist>
|
|
@ -219,6 +219,9 @@
|
|||
5B18BA7327C7BD8C0056EB19 /* LICENSE-JPN.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = "LICENSE-JPN.txt"; sourceTree = "<group>"; };
|
||||
5B18BA7427C7BD8C0056EB19 /* LICENSE-CHT.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = "LICENSE-CHT.txt"; sourceTree = "<group>"; };
|
||||
5B20430628BEE30900BFC6FD /* BookmarkManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarkManager.swift; sourceTree = "<group>"; };
|
||||
5B20430B28BEFC0C00BFC6FD /* vChewing.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = vChewing.entitlements; sourceTree = "<group>"; };
|
||||
5B20430C28BEFC1200BFC6FD /* vChewingPhraseEditor.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = vChewingPhraseEditor.entitlements; sourceTree = "<group>"; };
|
||||
5B20430D28BF279900BFC6FD /* vChewingInstaller.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = vChewingInstaller.entitlements; sourceTree = "<group>"; };
|
||||
5B21176B287539BB000443A9 /* ctlInputMethod_HandleStates.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ctlInputMethod_HandleStates.swift; sourceTree = "<group>"; };
|
||||
5B21176D28753B35000443A9 /* ctlInputMethod_HandleDisplay.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ctlInputMethod_HandleDisplay.swift; sourceTree = "<group>"; };
|
||||
5B21176F28753B9D000443A9 /* ctlInputMethod_Delegates.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ctlInputMethod_Delegates.swift; sourceTree = "<group>"; };
|
||||
|
@ -789,6 +792,9 @@
|
|||
6A0D4E9215FC0CFA00ABF4B3 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
5B20430D28BF279900BFC6FD /* vChewingInstaller.entitlements */,
|
||||
5B20430C28BEFC1200BFC6FD /* vChewingPhraseEditor.entitlements */,
|
||||
5B20430B28BEFC0C00BFC6FD /* vChewing.entitlements */,
|
||||
5BBD627827B6C4D900271480 /* Update-Info.plist */,
|
||||
5B18BA7027C7BD8B0056EB19 /* Makefile */,
|
||||
5B0C5EDE27C7D94C0078037C /* DataCompiler */,
|
||||
|
@ -1534,11 +1540,13 @@
|
|||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_ENTITLEMENTS = vChewingPhraseEditor.entitlements;
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 2201;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
|
@ -1584,11 +1592,13 @@
|
|||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_ENTITLEMENTS = vChewingPhraseEditor.entitlements;
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 2201;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
|
@ -1716,6 +1726,7 @@
|
|||
CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES;
|
||||
CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = vChewing.entitlements;
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
|
@ -1723,6 +1734,7 @@
|
|||
DEAD_CODE_STRIPPING = YES;
|
||||
DEVELOPMENT_ASSET_PATHS = "";
|
||||
DEVELOPMENT_TEAM = "";
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
|
@ -1773,6 +1785,7 @@
|
|||
CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES;
|
||||
CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = vChewing.entitlements;
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
|
@ -1780,6 +1793,7 @@
|
|||
DEAD_CODE_STRIPPING = YES;
|
||||
DEVELOPMENT_ASSET_PATHS = "";
|
||||
DEVELOPMENT_TEAM = "";
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
|
||||
|
@ -1818,12 +1832,14 @@
|
|||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = vChewingInstaller.entitlements;
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 2201;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
|
@ -1860,12 +1876,14 @@
|
|||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = vChewingInstaller.entitlements;
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 2201;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.files.bookmarks.app-scope</key>
|
||||
<true/>
|
||||
<key>com.apple.security.temporary-exception.files.home-relative-path.read-write</key>
|
||||
<array>
|
||||
<string>/Library/Input Methods/</string>
|
||||
</array>
|
||||
<key>com.apple.security.temporary-exception.shared-preference.read-write</key>
|
||||
<string>org.atelierInmu.vChewing.vChewingInstaller</string>
|
||||
</dict>
|
||||
</plist>
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.bookmarks.app-scope</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.user-selected.read-write</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
Loading…
Reference in New Issue