aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2021-09-22 19:22:44 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2021-09-22 19:22:44 +0200
commit7171df84fa57e577d5da3b17946a334e330abcb0 (patch)
tree9fb6befcb18ee3cbb93ad63d5e6cfdb451339301
parentKeychain: remove class constraint when copying (diff)
downloadwireguard-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>
-rw-r--r--Sources/Shared/FileManager+Extension.swift4
-rw-r--r--Sources/WireGuardApp/UI/macOS/AppDelegate.swift13
-rw-r--r--Sources/WireGuardApp/UI/macOS/LaunchedAtLoginDetector.swift29
-rw-r--r--Sources/WireGuardApp/UI/macOS/LoginItemHelper/Info.plist2
-rw-r--r--Sources/WireGuardApp/UI/macOS/LoginItemHelper/LoginItemHelper.entitlements4
-rw-r--r--Sources/WireGuardApp/UI/macOS/LoginItemHelper/main.m35
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;
}