该软件包现在是 SwiftSpellbook_macOS 的一部分

sEndpointSecurity

如果您觉得此库或其他我的库对您有所帮助,请请我吃披萨

简介

随着 macOS 10.15 Catalina 的发布,Apple 发布了一个出色的框架 EndpointSecurity。它是用户模式下 kAuth 和 MACF 机制的替代品,以前只能从内核访问。

该框架提供了很多功能...但它是纯 C 语言编写的

动机

sEndpointSecurity 是对 ES C API 的 Swift 封装,其编写主要基于以下三个目标

如果前两个目标很明显,那么第三个目标需要一些额外的解释。当您订阅文件身份验证事件时,这意味着在客户端返回解决方案之前,任何人都无法访问该文件。调试器是做什么的呢?在断点处,它会暂停应用程序(客户端)并阻止其响应任何事件。这会导致整个操作系统挂起,直到客户端被来自内核的 EndpontSecurity.kext 杀死。

sEndpointSecurity 提供了一种处理调试的方法 - 围绕 ES 客户端的 XPC 封装器。因此,我们将事件接收和响应转移到另一个进程,并通过 XPC 处理它。这允许我们调试应用程序。

API

很少有人喜欢没有代码示例的 ReadMe。这是代码示例

ESClient

ESClient 是围绕 EndpointSecurity C API 的 Swift 封装器,为了方便起见,它扩展了一些功能

import sEndpointSecurity

//  Create ESClient
var status: es_new_client_result_t = ES_NEW_CLIENT_RESULT_ERR_INTERNAL
guard let client = ESClient(status: &status) else {
    print("Failed to create ESClient. Status = \(status)")
    exit(1)
}

//  Register message handlers
client.authMessageHandler = { message, callback in
    print("Auth message: \(try! message.converted())")
    callback(.allowOnce)
}

client.notifyMessageHandler = { message in
    print("Notify message: \(try! message.converted())")
}

//  Start receiving messages
guard client.subscribe([ES_EVENT_TYPE_AUTH_EXEC, ES_EVENT_TYPE_NOTIFY_EXIT]) else {
    print("Failed to subscribe to ES messages")
    exit(2)
}


withExtendedLifetime(client) { RunLoop.main.run() }

基于 XPC 的 ES

ESXPCClient

ESXPCClient 是基于 XPC 的 ES 实现的客户端对应部分。它看起来非常像 ESClient,但由于异步 XPC 的特性,存在一些差异

import sEndpointSecurity

//  Create ESXPCClient
let client = ESXPCClient(NSXPCConnection(serviceName: "com.alkenso.ESXPC"))

//  Register message handlers
client.authMessageHandler = { message, callback in
    print("Auth message: \(try! message.converted())")
    callback(.allowOnce)
}

client.notifyMessageHandler = { message in
    print("Notify message: \(try! message.converted())")
}

let status = try! client.activate()
guard status == ES_NEW_CLIENT_RESULT_SUCCESS else {
    print("Failed to activate ESXPCClient. Status = \(status)")
    exit(1)
}

//  Start receiving messages
client.subscribe([ES_EVENT_TYPE_AUTH_EXEC, ES_EVENT_TYPE_NOTIFY_EXIT]) { result in
    guard result.success == true else {
        print("Failed to subscribe to ES events")
        exit(2)
    }
    print("Successfully subscribed to ES events")
}


withExtendedLifetime(client) {}

ESXPCService

ESXPCService 是基于 XPC 的 ES 实现的服务端对应部分。它是在实际使用 ES 框架的进程中创建的。

import sEndpointSecurity

let service = ESXPCService(
    listener: NSXPCListener.service(),
    createClient: ESClient.init
)
service.activate()

withExtendedLifetime(service) { RunLoop.main.run() }

依赖

该软件包的设计依赖性最低。目前,它只需要一个实用程序库 SwiftSpellbook(没有额外的依赖)