]> git.ipfire.org Git - thirdparty/wireguard-apple.git/commitdiff
WireGuardApp: use file to communicate launch-by-login-helper
authorJason A. Donenfeld <Jason@zx2c4.com>
Wed, 22 Sep 2021 17:22:44 +0000 (19:22 +0200)
committerJason A. Donenfeld <Jason@zx2c4.com>
Wed, 22 Sep 2021 17:22:44 +0000 (19:22 +0200)
Apple event params are broken on recent macOS versions.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Sources/Shared/FileManager+Extension.swift
Sources/WireGuardApp/UI/macOS/AppDelegate.swift
Sources/WireGuardApp/UI/macOS/LaunchedAtLoginDetector.swift
Sources/WireGuardApp/UI/macOS/LoginItemHelper/Info.plist
Sources/WireGuardApp/UI/macOS/LoginItemHelper/LoginItemHelper.entitlements
Sources/WireGuardApp/UI/macOS/LoginItemHelper/main.m

index 1b246fc4acde2ac457fa5b5bd3f6e191068bd904..a865b8167043eaaaa5d7021a0d2d41afaa7ea07c 100644 (file)
@@ -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)
index c56091e203370f47a2c5c64bd6f3b12d533e4995..f1ed4cd317055f462bff2a9801f2cfa58cf05871 100644 (file)
@@ -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")
index b3c6995a6968e1c3be1dce159222894324f5daea..57003e50958ca1218d506cf31b736ea70d0e8961 100644 (file)
@@ -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
-}
index 7334878406af99ac64c8a0108a7dd7aa8b4f760f..516eafdbf702f074f2cc3c9c439f162c6b234985 100644 (file)
@@ -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>
index 852fa1a4728ae4789e3bca55dd07caef3b41f2a5..557cb227b76513d9418ca189a868b07e96dd14a2 100644 (file)
@@ -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>
index 8d074d9505dc3b4591027cb33d34cd09f057d969..1c37daf8010fe517d1d562885d922adcb75f8b7b 100644 (file)
@@ -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;
 }