I'm using this code to get the path of an executable from the audit token provided in NEFilterDataProvider.handleNewFlow(_:), forwarded from the Network Extension to the main app via IPC:
private func securePathFromAuditToken(_ auditToken: Data) throws -> String? {
let secFlags = SecCSFlags()
var secCode: SecCode?
var status = SecCodeCopyGuestWithAttributes(nil, [kSecGuestAttributeAudit: auditToken] as CFDictionary, secFlags, &secCode)
guard let secCode = secCode else {
throw SecError(status)
}
var secStaticCode: SecStaticCode?
status = SecCodeCopyStaticCode(secCode, secFlags, &secStaticCode)
guard let secStaticCode = secStaticCode else {
throw SecError(status)
}
var url: CFURL?
status = SecCodeCopyPath(secStaticCode, secFlags, &url)
guard let url = url as URL? else {
throw NSError(domain: NSOSStatusErrorDomain, code: Int(status))
}
return nil
}
But it seems that some processes like trustd
, rapportd
, nsurlsessiond
and timed
have a non-nil path. For these executables I have to resort to this code, which I have read is not as secure:
private func insecurePathFromAuditToken(_ auditToken: Data) throws -> String? {
if auditToken.count == MemoryLayout<audit_token_t>.size {
let pid = auditToken.withUnsafeBytes { buffer in
audit_token_to_pid(buffer.baseAddress!.assumingMemoryBound(to: audit_token_t.self).pointee)
}
let pathbuf = UnsafeMutablePointer<Int8>.allocate(capacity: Int(PROC_PIDPATHINFO_SIZE))
defer {
pathbuf.deallocate()
}
let ret = proc_pidpath(pid, pathbuf, UInt32(PROC_PIDPATHINFO_SIZE))
if ret <= 0 {
throw NSError(domain: NSPOSIXErrorDomain, code: Int(errno))
}
return String(cString: pathbuf)
}
return nil
}
This seems to happen with both NEFilterFlow.sourceAppAuditToken and sourceProcessAuditToken. Is this expected? Can it really be that some executables shipped with macOS are not signed?