mirror of
https://github.com/XcodesOrg/XcodesApp.git
synced 2026-03-25 08:55:46 +00:00
Merge pull request #59 from RobotsAndPencils/xpc-connection-bug
Fold HelperInstaller into HelperClient, improve error handling and logging
This commit is contained in:
commit
23df4a8c3a
5 changed files with 149 additions and 60 deletions
|
|
@ -39,19 +39,18 @@
|
|||
CA9FF8DB25959B4000E47BAF /* XPCDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA9FF8DA25959B4000E47BAF /* XPCDelegate.swift */; };
|
||||
CA9FF8E025959BAA00E47BAF /* ConnectionVerifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA9FF8DF25959BAA00E47BAF /* ConnectionVerifier.swift */; };
|
||||
CA9FF8E625959BB800E47BAF /* AuditTokenHack.m in Sources */ = {isa = PBXBuildFile; fileRef = CA9FF8E525959BB800E47BAF /* AuditTokenHack.m */; };
|
||||
CA9FF8F525959CE000E47BAF /* HelperInstaller.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA9FF8F425959CE000E47BAF /* HelperInstaller.swift */; };
|
||||
CA9FF9362595B44700E47BAF /* HelperClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA9FF9352595B44700E47BAF /* HelperClient.swift */; };
|
||||
CAA1CB2D255A5262003FD669 /* AppleAPI in Frameworks */ = {isa = PBXBuildFile; productRef = CAA1CB2C255A5262003FD669 /* AppleAPI */; };
|
||||
CAA1CB35255A5AD5003FD669 /* SignInCredentialsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAA1CB34255A5AD5003FD669 /* SignInCredentialsView.swift */; };
|
||||
CAA1CB45255A5B60003FD669 /* SignIn2FAView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAA1CB44255A5B60003FD669 /* SignIn2FAView.swift */; };
|
||||
CAA1CB49255A5C97003FD669 /* SignInSMSView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAA1CB48255A5C97003FD669 /* SignInSMSView.swift */; };
|
||||
CAA1CB4D255A5CFD003FD669 /* SignInPhoneListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAA1CB4C255A5CFD003FD669 /* SignInPhoneListView.swift */; };
|
||||
CAA858CD25A3D8BC00ACF8C0 /* ErrorHandling in Frameworks */ = {isa = PBXBuildFile; productRef = CAA858CC25A3D8BC00ACF8C0 /* ErrorHandling */; };
|
||||
CAA8587C25A2B37900ACF8C0 /* IsTesting.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAA8587B25A2B37900ACF8C0 /* IsTesting.swift */; };
|
||||
CAA8589325A2B77E00ACF8C0 /* aria2c in Copy aria2c */ = {isa = PBXBuildFile; fileRef = CAA8588025A2B63A00ACF8C0 /* aria2c */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
|
||||
CAA8589B25A2B83000ACF8C0 /* Aria2CError.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAA8589A25A2B83000ACF8C0 /* Aria2CError.swift */; };
|
||||
CAA858DB25A3E11F00ACF8C0 /* aria2-release-1.35.0.tar.gz in Resources */ = {isa = PBXBuildFile; fileRef = CAA858DA25A3E11F00ACF8C0 /* aria2-release-1.35.0.tar.gz */; };
|
||||
CAA858C425A2BE4E00ACF8C0 /* Downloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAA858C325A2BE4E00ACF8C0 /* Downloader.swift */; };
|
||||
CAA858CD25A3D8BC00ACF8C0 /* ErrorHandling in Frameworks */ = {isa = PBXBuildFile; productRef = CAA858CC25A3D8BC00ACF8C0 /* ErrorHandling */; };
|
||||
CAA858DB25A3E11F00ACF8C0 /* aria2-release-1.35.0.tar.gz in Resources */ = {isa = PBXBuildFile; fileRef = CAA858DA25A3E11F00ACF8C0 /* aria2-release-1.35.0.tar.gz */; };
|
||||
CABFA9BB2592EEEA00380FEE /* DateFormatter+.swift in Sources */ = {isa = PBXBuildFile; fileRef = CABFA9BA2592EEEA00380FEE /* DateFormatter+.swift */; };
|
||||
CABFA9BD2592EEEA00380FEE /* Environment.swift in Sources */ = {isa = PBXBuildFile; fileRef = CABFA9A92592EEE900380FEE /* Environment.swift */; };
|
||||
CABFA9BF2592EEEA00380FEE /* URLSession+DownloadTaskPublisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = CABFA9B32592EEEA00380FEE /* URLSession+DownloadTaskPublisher.swift */; };
|
||||
|
|
@ -188,7 +187,6 @@
|
|||
CA9FF8E425959BB800E47BAF /* AuditTokenHack.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AuditTokenHack.h; sourceTree = "<group>"; };
|
||||
CA9FF8E525959BB800E47BAF /* AuditTokenHack.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AuditTokenHack.m; sourceTree = "<group>"; };
|
||||
CA9FF8EA25959BDD00E47BAF /* com.robotsandpencils.XcodesApp.Helper-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "com.robotsandpencils.XcodesApp.Helper-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||
CA9FF8F425959CE000E47BAF /* HelperInstaller.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HelperInstaller.swift; sourceTree = "<group>"; };
|
||||
CA9FF9052595A28400E47BAF /* com.robotsandpencils.XcodesApp.HelperTest.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = com.robotsandpencils.XcodesApp.HelperTest.entitlements; sourceTree = "<group>"; };
|
||||
CA9FF9252595A7EB00E47BAF /* Scripts */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Scripts; sourceTree = "<group>"; };
|
||||
CA9FF9352595B44700E47BAF /* HelperClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HelperClient.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -200,8 +198,8 @@
|
|||
CAA8588025A2B63A00ACF8C0 /* aria2c */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; path = aria2c; sourceTree = "<group>"; };
|
||||
CAA8588A25A2B69300ACF8C0 /* aria2c.LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = aria2c.LICENSE; sourceTree = "<group>"; };
|
||||
CAA8589A25A2B83000ACF8C0 /* Aria2CError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Aria2CError.swift; sourceTree = "<group>"; };
|
||||
CAA858DA25A3E11F00ACF8C0 /* aria2-release-1.35.0.tar.gz */ = {isa = PBXFileReference; lastKnownFileType = archive.gzip; path = "aria2-release-1.35.0.tar.gz"; sourceTree = "<group>"; };
|
||||
CAA858C325A2BE4E00ACF8C0 /* Downloader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Downloader.swift; sourceTree = "<group>"; };
|
||||
CAA858DA25A3E11F00ACF8C0 /* aria2-release-1.35.0.tar.gz */ = {isa = PBXFileReference; lastKnownFileType = archive.gzip; path = "aria2-release-1.35.0.tar.gz"; sourceTree = "<group>"; };
|
||||
CABFA9A02592EAF500380FEE /* R&PLogo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "R&PLogo.png"; sourceTree = "<group>"; };
|
||||
CABFA9A12592EAFB00380FEE /* LICENSE */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; };
|
||||
CABFA9A32592ED5700380FEE /* Apple.paw */ = {isa = PBXFileReference; lastKnownFileType = file; name = Apple.paw; path = ../xcodes/Apple.paw; sourceTree = "<group>"; };
|
||||
|
|
@ -409,7 +407,6 @@
|
|||
CABFA9B82592EEEA00380FEE /* FileManager+.swift */,
|
||||
CAFBDB942598FE96003DCC5A /* FocusedValues.swift */,
|
||||
CABFA9AC2592EEE900380FEE /* Foundation.swift */,
|
||||
CA9FF8F425959CE000E47BAF /* HelperInstaller.swift */,
|
||||
CA9FF9352595B44700E47BAF /* HelperClient.swift */,
|
||||
CAC281D9259F985100B8AB0B /* InstallationStep.swift */,
|
||||
CA9FF8862595607900E47BAF /* InstalledXcode.swift */,
|
||||
|
|
@ -754,7 +751,6 @@
|
|||
CAA1CB35255A5AD5003FD669 /* SignInCredentialsView.swift in Sources */,
|
||||
CA9FF877259528CC00E47BAF /* Version+XcodeReleases.swift in Sources */,
|
||||
CABFAA2D2592FBFC00380FEE /* Configure.swift in Sources */,
|
||||
CA9FF8F525959CE000E47BAF /* HelperInstaller.swift in Sources */,
|
||||
CA73510D257BFCEF00EA9CF8 /* NSAttributedString+.swift in Sources */,
|
||||
CAFBDB952598FE96003DCC5A /* FocusedValues.swift in Sources */,
|
||||
CAC281CD259F97FA00B8AB0B /* ObservingProgressIndicator.swift in Sources */,
|
||||
|
|
|
|||
|
|
@ -237,7 +237,7 @@ public struct Defaults {
|
|||
|
||||
private let helperClient = HelperClient()
|
||||
public struct Helper {
|
||||
var install: () -> Void = HelperInstaller.install
|
||||
var install: () -> Void = helperClient.install
|
||||
var checkIfLatestHelperIsInstalled: () -> AnyPublisher<Bool, Never> = helperClient.checkIfLatestHelperIsInstalled
|
||||
var getVersion: () -> AnyPublisher<String, Error> = helperClient.getVersion
|
||||
var switchXcodePath: (_ absolutePath: String) -> AnyPublisher<Void, Error> = helperClient.switchXcodePath
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
import Combine
|
||||
import Foundation
|
||||
import os.log
|
||||
import ServiceManagement
|
||||
|
||||
final class HelperClient {
|
||||
private var connection: NSXPCConnection?
|
||||
|
|
@ -34,26 +36,35 @@ final class HelperClient {
|
|||
}
|
||||
|
||||
func checkIfLatestHelperIsInstalled() -> AnyPublisher<Bool, Never> {
|
||||
Logger.helperClient.info(#function)
|
||||
|
||||
let helperURL = Bundle.main.bundleURL.appendingPathComponent("Contents/Library/LaunchServices/" + machServiceName)
|
||||
guard
|
||||
let helperBundleInfo = CFBundleCopyInfoDictionaryForURL(helperURL as CFURL) as? [String: Any],
|
||||
let bundledHelperVersion = helperBundleInfo["CFBundleShortVersionString"] as? String
|
||||
else {
|
||||
return Just(false).eraseToAnyPublisher()
|
||||
return Just(false)
|
||||
.handleEvents(receiveOutput: { Logger.helperClient.info("\(#function): \(String(describing: $0))") })
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
return getVersion()
|
||||
.map { installedHelperVersion in installedHelperVersion == bundledHelperVersion }
|
||||
.catch { _ in Just(false) }
|
||||
// Failure is Never, so don't bother logging completion
|
||||
.handleEvents(receiveOutput: { Logger.helperClient.info("\(#function): \(String(describing: $0), privacy: .public)") })
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
func getVersion() -> AnyPublisher<String, Error> {
|
||||
Logger.helperClient.info(#function)
|
||||
|
||||
let connectionErrorSubject = PassthroughSubject<String, Error>()
|
||||
guard
|
||||
let helper = self.helper(errorSubject: connectionErrorSubject)
|
||||
else {
|
||||
return Fail(error: NSError())
|
||||
return Fail(error: HelperClientError.failedToCreateRemoteObjectProxy)
|
||||
.handleEvents(receiveCompletion: { Logger.helperClient.error("\(#function): \(String(describing: $0))") })
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
|
|
@ -71,15 +82,27 @@ final class HelperClient {
|
|||
.map { _ in Void() }
|
||||
)
|
||||
.map { $0.0 }
|
||||
.handleEvents(receiveOutput: { Logger.helperClient.info("\(#function): \(String(describing: $0), privacy: .public)") },
|
||||
receiveCompletion: { completion in
|
||||
switch completion {
|
||||
case .finished:
|
||||
Logger.helperClient.info("\(#function): finished")
|
||||
case let .failure(error):
|
||||
Logger.helperClient.error("\(#function): \(String(describing: error))")
|
||||
}
|
||||
})
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
func switchXcodePath(_ absolutePath: String) -> AnyPublisher<Void, Error> {
|
||||
Logger.helperClient.info("\(#function): \(absolutePath, privacy: .private(mask: .hash))")
|
||||
|
||||
let connectionErrorSubject = PassthroughSubject<String, Error>()
|
||||
guard
|
||||
let helper = self.helper(errorSubject: connectionErrorSubject)
|
||||
else {
|
||||
return Fail(error: NSError())
|
||||
return Fail(error: HelperClientError.failedToCreateRemoteObjectProxy)
|
||||
.handleEvents(receiveCompletion: { Logger.helperClient.error("\(#function): \(String(describing: $0))") })
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
|
|
@ -101,15 +124,27 @@ final class HelperClient {
|
|||
.map { _ in Void() }
|
||||
)
|
||||
.map { $0.0 }
|
||||
.handleEvents(receiveOutput: { Logger.helperClient.info("\(#function): \(String(describing: $0))") },
|
||||
receiveCompletion: { completion in
|
||||
switch completion {
|
||||
case .finished:
|
||||
Logger.helperClient.info("\(#function): finished")
|
||||
case let .failure(error):
|
||||
Logger.helperClient.error("\(#function): \(String(describing: error))")
|
||||
}
|
||||
})
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
func devToolsSecurityEnable() -> AnyPublisher<Void, Error> {
|
||||
Logger.helperClient.info(#function)
|
||||
|
||||
let connectionErrorSubject = PassthroughSubject<String, Error>()
|
||||
guard
|
||||
let helper = self.helper(errorSubject: connectionErrorSubject)
|
||||
else {
|
||||
return Fail(error: NSError())
|
||||
return Fail(error: HelperClientError.failedToCreateRemoteObjectProxy)
|
||||
.handleEvents(receiveCompletion: { Logger.helperClient.error("\(#function): \(String(describing: $0))") })
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
|
|
@ -131,15 +166,27 @@ final class HelperClient {
|
|||
.map { _ in Void() }
|
||||
)
|
||||
.map { $0.0 }
|
||||
.handleEvents(receiveOutput: { Logger.helperClient.info("\(#function): \(String(describing: $0))") },
|
||||
receiveCompletion: { completion in
|
||||
switch completion {
|
||||
case .finished:
|
||||
Logger.helperClient.info("\(#function): finished")
|
||||
case let .failure(error):
|
||||
Logger.helperClient.error("\(#function): \(String(describing: error))")
|
||||
}
|
||||
})
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
func addStaffToDevelopersGroup() -> AnyPublisher<Void, Error> {
|
||||
Logger.helperClient.info(#function)
|
||||
|
||||
let connectionErrorSubject = PassthroughSubject<String, Error>()
|
||||
guard
|
||||
let helper = self.helper(errorSubject: connectionErrorSubject)
|
||||
else {
|
||||
return Fail(error: NSError())
|
||||
return Fail(error: HelperClientError.failedToCreateRemoteObjectProxy)
|
||||
.handleEvents(receiveCompletion: { Logger.helperClient.error("\(#function): \(String(describing: $0))") })
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
|
|
@ -161,15 +208,27 @@ final class HelperClient {
|
|||
.map { _ in Void() }
|
||||
)
|
||||
.map { $0.0 }
|
||||
.handleEvents(receiveOutput: { Logger.helperClient.info("\(#function): \(String(describing: $0))") },
|
||||
receiveCompletion: { completion in
|
||||
switch completion {
|
||||
case .finished:
|
||||
Logger.helperClient.info("\(#function): finished")
|
||||
case let .failure(error):
|
||||
Logger.helperClient.error("\(#function): \(String(describing: error))")
|
||||
}
|
||||
})
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
func acceptXcodeLicense(absoluteXcodePath: String) -> AnyPublisher<Void, Error> {
|
||||
Logger.helperClient.info("\(#function): \(absoluteXcodePath, privacy: .private(mask: .hash))")
|
||||
|
||||
let connectionErrorSubject = PassthroughSubject<String, Error>()
|
||||
guard
|
||||
let helper = self.helper(errorSubject: connectionErrorSubject)
|
||||
else {
|
||||
return Fail(error: NSError())
|
||||
return Fail(error: HelperClientError.failedToCreateRemoteObjectProxy)
|
||||
.handleEvents(receiveCompletion: { Logger.helperClient.error("\(#function): \(String(describing: $0))") })
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
|
|
@ -191,15 +250,27 @@ final class HelperClient {
|
|||
.map { _ in Void() }
|
||||
)
|
||||
.map { $0.0 }
|
||||
.handleEvents(receiveOutput: { Logger.helperClient.info("\(#function): \(String(describing: $0))") },
|
||||
receiveCompletion: { completion in
|
||||
switch completion {
|
||||
case .finished:
|
||||
Logger.helperClient.info("\(#function): finished")
|
||||
case let .failure(error):
|
||||
Logger.helperClient.error("\(#function): \(String(describing: error))")
|
||||
}
|
||||
})
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
func runFirstLaunch(absoluteXcodePath: String) -> AnyPublisher<Void, Error> {
|
||||
Logger.helperClient.info("\(#function): \(absoluteXcodePath, privacy: .private(mask: .hash))")
|
||||
|
||||
let connectionErrorSubject = PassthroughSubject<String, Error>()
|
||||
guard
|
||||
let helper = self.helper(errorSubject: connectionErrorSubject)
|
||||
else {
|
||||
return Fail(error: NSError())
|
||||
return Fail(error: HelperClientError.failedToCreateRemoteObjectProxy)
|
||||
.handleEvents(receiveCompletion: { Logger.helperClient.error("\(#function): \(String(describing: $0))") })
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
|
|
@ -221,6 +292,72 @@ final class HelperClient {
|
|||
.map { _ in Void() }
|
||||
)
|
||||
.map { $0.0 }
|
||||
.handleEvents(receiveOutput: { Logger.helperClient.info("\(#function): \(String(describing: $0))") },
|
||||
receiveCompletion: { completion in
|
||||
switch completion {
|
||||
case .finished:
|
||||
Logger.helperClient.info("\(#function): finished")
|
||||
case let .failure(error):
|
||||
Logger.helperClient.error("\(#function): \(String(describing: error))")
|
||||
}
|
||||
})
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
// MARK: - Install
|
||||
// From https://github.com/securing/SimpleXPCApp/
|
||||
|
||||
func install() {
|
||||
Logger.helperClient.info(#function)
|
||||
|
||||
var authItem = kSMRightBlessPrivilegedHelper.withCString { name in
|
||||
AuthorizationItem(name: name, valueLength: 0, value:UnsafeMutableRawPointer(bitPattern: 0), flags: 0)
|
||||
}
|
||||
var authRights = withUnsafeMutablePointer(to: &authItem) { authItem in
|
||||
AuthorizationRights(count: 1, items: authItem)
|
||||
}
|
||||
|
||||
do {
|
||||
let authRef = try authorizationRef(&authRights, nil, [.interactionAllowed, .extendRights, .preAuthorize])
|
||||
var cfError: Unmanaged<CFError>?
|
||||
SMJobBless(kSMDomainSystemLaunchd, machServiceName as CFString, authRef, &cfError)
|
||||
if let error = cfError?.takeRetainedValue() { throw error }
|
||||
|
||||
self.connection?.invalidate()
|
||||
self.connection = nil
|
||||
|
||||
Logger.helperClient.info("\(#function): Finished installation")
|
||||
} catch {
|
||||
Logger.helperClient.error("\(#function): \(error.localizedDescription)")
|
||||
}
|
||||
}
|
||||
|
||||
private func executeAuthorizationFunction(_ authorizationFunction: () -> (OSStatus) ) throws {
|
||||
let osStatus = authorizationFunction()
|
||||
guard osStatus == errAuthorizationSuccess else {
|
||||
throw HelperClientError.message(String(describing: SecCopyErrorMessageString(osStatus, nil)))
|
||||
}
|
||||
}
|
||||
|
||||
func authorizationRef(_ rights: UnsafePointer<AuthorizationRights>?,
|
||||
_ environment: UnsafePointer<AuthorizationEnvironment>?,
|
||||
_ flags: AuthorizationFlags) throws -> AuthorizationRef? {
|
||||
var authRef: AuthorizationRef?
|
||||
try executeAuthorizationFunction { AuthorizationCreate(rights, environment, flags, &authRef) }
|
||||
return authRef
|
||||
}
|
||||
}
|
||||
|
||||
enum HelperClientError: LocalizedError {
|
||||
case failedToCreateRemoteObjectProxy
|
||||
case message(String)
|
||||
|
||||
var errorDescription: String? {
|
||||
switch self {
|
||||
case .failedToCreateRemoteObjectProxy:
|
||||
return "Unable to communicate with privileged helper."
|
||||
case let .message(message):
|
||||
return message
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,44 +0,0 @@
|
|||
// From https://github.com/securing/SimpleXPCApp/
|
||||
|
||||
import Foundation
|
||||
import os.log
|
||||
import ServiceManagement
|
||||
|
||||
enum HelperAuthorizationError: Error {
|
||||
case message(String)
|
||||
}
|
||||
|
||||
class HelperInstaller {
|
||||
private static func executeAuthorizationFunction(_ authorizationFunction: () -> (OSStatus) ) throws {
|
||||
let osStatus = authorizationFunction()
|
||||
guard osStatus == errAuthorizationSuccess else {
|
||||
throw HelperAuthorizationError.message(String(describing: SecCopyErrorMessageString(osStatus, nil)))
|
||||
}
|
||||
}
|
||||
|
||||
static func authorizationRef(_ rights: UnsafePointer<AuthorizationRights>?,
|
||||
_ environment: UnsafePointer<AuthorizationEnvironment>?,
|
||||
_ flags: AuthorizationFlags) throws -> AuthorizationRef? {
|
||||
var authRef: AuthorizationRef?
|
||||
try executeAuthorizationFunction { AuthorizationCreate(rights, environment, flags, &authRef) }
|
||||
return authRef
|
||||
}
|
||||
|
||||
static func install() {
|
||||
var authItem = kSMRightBlessPrivilegedHelper.withCString { name in
|
||||
AuthorizationItem(name: name, valueLength: 0, value:UnsafeMutableRawPointer(bitPattern: 0), flags: 0)
|
||||
}
|
||||
var authRights = withUnsafeMutablePointer(to: &authItem) { authItem in
|
||||
AuthorizationRights(count: 1, items: authItem)
|
||||
}
|
||||
|
||||
do {
|
||||
let authRef = try authorizationRef(&authRights, nil, [.interactionAllowed, .extendRights, .preAuthorize])
|
||||
var cfError: Unmanaged<CFError>?
|
||||
SMJobBless(kSMDomainSystemLaunchd, machServiceName as CFString, authRef, &cfError)
|
||||
if let error = cfError?.takeRetainedValue() { throw error }
|
||||
} catch {
|
||||
Logger.helperInstaller.error("\(error.localizedDescription)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,6 +5,6 @@ extension Logger {
|
|||
private static var subsystem = Bundle.main.bundleIdentifier!
|
||||
|
||||
static let appState = Logger(subsystem: subsystem, category: "appState")
|
||||
static let helperInstaller = Logger(subsystem: subsystem, category: "helperInstaller")
|
||||
static let helperClient = Logger(subsystem: subsystem, category: "helperClient")
|
||||
static let subprocess = Logger(subsystem: subsystem, category: "subprocess")
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue