diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2021-09-22 19:22:44 +0200 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2021-09-22 19:22:44 +0200 |
commit | 7171df84fa57e577d5da3b17946a334e330abcb0 (patch) | |
tree | 9fb6befcb18ee3cbb93ad63d5e6cfdb451339301 | |
parent | Keychain: remove class constraint when copying (diff) | |
download | wireguard-apple-7171df84fa57e577d5da3b17946a334e330abcb0.tar.xz wireguard-apple-7171df84fa57e577d5da3b17946a334e330abcb0.zip |
WireGuardApp: use file to communicate launch-by-login-helper
Apple event params are broken on recent macOS versions.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
6 files changed, 47 insertions, 40 deletions
diff --git a/Sources/Shared/FileManager+Extension.swift b/Sources/Shared/FileManager+Extension.swift index 1b246fc..a865b81 100644 --- a/Sources/Shared/FileManager+Extension.swift +++ b/Sources/Shared/FileManager+Extension.swift @@ -35,6 +35,10 @@ extension FileManager { return sharedFolderURL?.appendingPathComponent("last-error.txt") } + static var loginHelperTimestampURL: URL? { + return sharedFolderURL?.appendingPathComponent("login-helper-timestamp.bin") + } + static func deleteFile(at url: URL) -> Bool { do { try FileManager.default.removeItem(at: url) diff --git a/Sources/WireGuardApp/UI/macOS/AppDelegate.swift b/Sources/WireGuardApp/UI/macOS/AppDelegate.swift index c56091e..f1ed4cd 100644 --- a/Sources/WireGuardApp/UI/macOS/AppDelegate.swift +++ b/Sources/WireGuardApp/UI/macOS/AppDelegate.swift @@ -65,19 +65,6 @@ class AppDelegate: NSObject, NSApplicationDelegate { } } - func applicationShouldHandleReopen(_ sender: NSApplication, hasVisibleWindows: Bool) -> Bool { - if let appleEvent = NSAppleEventManager.shared().currentAppleEvent { - if LaunchedAtLoginDetector.isReopenedByLoginItemHelper(reopenAppleEvent: appleEvent) { - return false - } - } - if hasVisibleWindows { - return true - } - showManageTunnelsWindow(completion: nil) - return false - } - @objc func confirmAndQuit() { let alert = NSAlert() alert.messageText = tr("macConfirmAndQuitAlertMessage") diff --git a/Sources/WireGuardApp/UI/macOS/LaunchedAtLoginDetector.swift b/Sources/WireGuardApp/UI/macOS/LaunchedAtLoginDetector.swift index b3c6995..57003e5 100644 --- a/Sources/WireGuardApp/UI/macOS/LaunchedAtLoginDetector.swift +++ b/Sources/WireGuardApp/UI/macOS/LaunchedAtLoginDetector.swift @@ -4,25 +4,16 @@ import Cocoa class LaunchedAtLoginDetector { - static let launchCode = "LaunchedByWireGuardLoginItemHelper" - static func isLaunchedAtLogin(openAppleEvent: NSAppleEventDescriptor) -> Bool { - guard isOpenEvent(openAppleEvent) else { return false } - guard let propData = openAppleEvent.paramDescriptor(forKeyword: keyAEPropData) else { return false } - return propData.stringValue == launchCode - } - - static func isReopenedByLoginItemHelper(reopenAppleEvent: NSAppleEventDescriptor) -> Bool { - guard isReopenEvent(reopenAppleEvent) else { return false } - guard let propData = reopenAppleEvent.paramDescriptor(forKeyword: keyAEPropData) else { return false } - return propData.stringValue == launchCode + let now = clock_gettime_nsec_np(CLOCK_UPTIME_RAW) + guard openAppleEvent.eventClass == kCoreEventClass && openAppleEvent.eventID == kAEOpenApplication else { return false } + guard let url = FileManager.loginHelperTimestampURL else { return false } + guard let data = try? Data(contentsOf: url) else { return false } + _ = FileManager.deleteFile(at: url) + guard data.count == 8 else { return false } + let then = data.withUnsafeBytes { ptr in + ptr.load(as: UInt64.self) + } + return now - then <= 5000000000 } } - -private func isOpenEvent(_ event: NSAppleEventDescriptor) -> Bool { - return event.eventClass == kCoreEventClass && event.eventID == kAEOpenApplication -} - -private func isReopenEvent(_ event: NSAppleEventDescriptor) -> Bool { - return event.eventClass == kCoreEventClass && event.eventID == kAEReopenApplication -} diff --git a/Sources/WireGuardApp/UI/macOS/LoginItemHelper/Info.plist b/Sources/WireGuardApp/UI/macOS/LoginItemHelper/Info.plist index 7334878..516eafd 100644 --- a/Sources/WireGuardApp/UI/macOS/LoginItemHelper/Info.plist +++ b/Sources/WireGuardApp/UI/macOS/LoginItemHelper/Info.plist @@ -32,5 +32,7 @@ <true/> <key>com.wireguard.macos.app_id</key> <string>$(APP_ID_MACOS)</string> + <key>com.wireguard.macos.app_group_id</key> + <string>$(DEVELOPMENT_TEAM).group.$(APP_ID_MACOS)</string> </dict> </plist> diff --git a/Sources/WireGuardApp/UI/macOS/LoginItemHelper/LoginItemHelper.entitlements b/Sources/WireGuardApp/UI/macOS/LoginItemHelper/LoginItemHelper.entitlements index 852fa1a..557cb22 100644 --- a/Sources/WireGuardApp/UI/macOS/LoginItemHelper/LoginItemHelper.entitlements +++ b/Sources/WireGuardApp/UI/macOS/LoginItemHelper/LoginItemHelper.entitlements @@ -4,5 +4,9 @@ <dict> <key>com.apple.security.app-sandbox</key> <true/> + <key>com.apple.security.application-groups</key> + <array> + <string>$(DEVELOPMENT_TEAM).group.$(APP_ID_MACOS)</string> + </array> </dict> </plist> diff --git a/Sources/WireGuardApp/UI/macOS/LoginItemHelper/main.m b/Sources/WireGuardApp/UI/macOS/LoginItemHelper/main.m index 8d074d9..1c37daf 100644 --- a/Sources/WireGuardApp/UI/macOS/LoginItemHelper/main.m +++ b/Sources/WireGuardApp/UI/macOS/LoginItemHelper/main.m @@ -5,13 +5,32 @@ int main(int argc, char *argv[]) { - NSString *appIdInfoDictionaryKey = @"com.wireguard.macos.app_id"; - NSString *appId = [NSBundle.mainBundle objectForInfoDictionaryKey:appIdInfoDictionaryKey]; - - NSString *launchCode = @"LaunchedByWireGuardLoginItemHelper"; - NSAppleEventDescriptor *paramDescriptor = [NSAppleEventDescriptor descriptorWithString:launchCode]; - - [NSWorkspace.sharedWorkspace launchAppWithBundleIdentifier:appId options:NSWorkspaceLaunchWithoutActivation - additionalEventParamDescriptor:paramDescriptor launchIdentifier:NULL]; + NSString *appId = [NSBundle.mainBundle objectForInfoDictionaryKey:@"com.wireguard.macos.app_id"]; + NSString *appGroupId = [NSBundle.mainBundle objectForInfoDictionaryKey:@"com.wireguard.macos.app_group_id"]; + if (!appId || !appGroupId) + return 1; + NSURL *containerUrl = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:appGroupId]; + if (!containerUrl) + return 2; + uint64_t now = clock_gettime_nsec_np(CLOCK_UPTIME_RAW); + if (![[NSData dataWithBytes:&now length:sizeof(now)] writeToURL:[containerUrl URLByAppendingPathComponent:@"login-helper-timestamp.bin"] atomically:YES]) + return 3; + if (@available(macOS 10.15, *)) { + NSCondition *condition = [[NSCondition alloc] init]; + NSURL *appURL = [NSWorkspace.sharedWorkspace URLForApplicationWithBundleIdentifier:appId]; + if (!appURL) + return 4; + NSWorkspaceOpenConfiguration *openConfiguration = [NSWorkspaceOpenConfiguration configuration]; + openConfiguration.activates = NO; + openConfiguration.addsToRecentItems = NO; + openConfiguration.hides = YES; + [NSWorkspace.sharedWorkspace openApplicationAtURL:appURL configuration:openConfiguration completionHandler:^(NSRunningApplication * _Nullable app, NSError * _Nullable error) { + [condition signal]; + }]; + [condition wait]; + } else { + [NSWorkspace.sharedWorkspace launchAppWithBundleIdentifier:appId options:NSWorkspaceLaunchWithoutActivation + additionalEventParamDescriptor:NULL launchIdentifier:NULL]; + } return 0; } |