// // SMJobLessAuthorization.swift // main // // Created by Jura on 3/12/20. // Copyright © 2020 Juraldinio. All rights reserved. // import Foundation import ServiceManagement final class SMJobLessAuthorization { enum SMJobLessAuthorizationError: Error { case message(String) } private static var authRef: AuthorizationRef? // MARK: - Interface // Install and activate the helper inside our application bundle to disk. static func install(executable label: String) -> Bool { guard let authRef = self.getAuthRef() else { return false } var cfError: Unmanaged? let success = SMJobBless(kSMDomainSystemLaunchd, label as CFString, authRef, &cfError) if cfError?.takeRetainedValue() != nil { return false } return success } static func dropAuth() { self.authRef = nil } // MARK: - Private private static func getAuthRef() -> AuthorizationRef? { if let authRef = self.authRef { return authRef } var authItem = AuthorizationItem(name: kSMRightBlessPrivilegedHelper, valueLength: 0, value: UnsafeMutableRawPointer(bitPattern: 0), flags: 0) var authRights = AuthorizationRights(count: 1, items: &authItem) do { if let authRef = try self.authorizationRef(&authRights, nil, [.interactionAllowed, .extendRights, .preAuthorize]) { self.authRef = authRef } } catch {} return self.authRef } private static func authorizationRef(_ rights: UnsafePointer?, _ environment: UnsafePointer?, _ flags: AuthorizationFlags) throws -> AuthorizationRef? { var authRef: AuthorizationRef? try executeAuthorizationFunction { AuthorizationCreate(rights, environment, flags, &authRef) } return authRef } private static func executeAuthorizationFunction(_ authorizationFunction: () -> (OSStatus) ) throws { let osStatus = authorizationFunction() guard osStatus == errAuthorizationSuccess else { throw SMJobLessAuthorizationError.message(String(describing: SecCopyErrorMessageString(osStatus, nil))) } } }