I have developed a sample app following the example found Updating your app package installer to use the new Service Management API and referring this discussion on XPC Security.
The app is working fine, I have used Swift NSXPCConnection
in favour of xpc_connection_create_mach_service
used in the example. (I am running app directly from Xcode)
I am trying to set up security requirements for the client connection using setCodeSigningRequirement
on the connection instance.
But it fails for even basic requirement connection.setCodeSigningRequirement("anchor apple")
.
Error is as follows.
cannot open file at line 46986 of [554764a6e7]
os_unix.c:46986: (0) open(/private/var/db/DetachedSignatures) - Undefined error: 0
xpc_support_check_token: anchor apple error: Error Domain=NSOSStatusErrorDomain Code=-67050 "(null)" status: -67050
I have used codesign -d --verbose=4 /path/to/executable
to check the attributes I do get them in the terminal.
Other way round, I have tried XPC service provider sending back process id (pid) with each request, and I am probing this id to get attributes using this code which gives all the details.
func inspectCodeSignature(ofPIDString pidString: String) {
guard let pid = pid_t(pidString) else {
print("Invalid PID string: \(pidString)")
return
}
let attributes = [kSecGuestAttributePid: pid] as CFDictionary
var codeRef: SecCode?
let status = SecCodeCopyGuestWithAttributes(nil, attributes, [], &codeRef)
guard status == errSecSuccess, let code = codeRef else {
print("Failed to get SecCode for PID \(pid) (status: \(status))")
return
}
var staticCode: SecStaticCode?
let staticStatus = SecCodeCopyStaticCode(code, [], &staticCode)
guard staticStatus == errSecSuccess, let staticCodeRef = staticCode else {
print("Failed to get SecStaticCode (status: \(staticStatus))")
return
}
var infoDict: CFDictionary?
if SecCodeCopySigningInformation(staticCodeRef, SecCSFlags(rawValue: kSecCSSigningInformation), &infoDict) == errSecSuccess,
let info = infoDict as? [String: Any] {
print("🔍 Code Signing Info for PID \(pid):")
print("• Identifier: \(info["identifier"] ?? "N/A")")
print("• Team ID: \(info["teamid"] ?? "N/A")")
if let entitlements = info["entitlements-dict"] as? [String: Any] {
print("• Entitlements:")
for (key, value) in entitlements {
print(" - \(key): \(value)")
}
}
} else {
print("Failed to retrieve signing information.")
}
var requirement: SecRequirement?
if SecRequirementCreateWithString("anchor apple" as CFString, [], &requirement) == errSecSuccess,
let req = requirement {
let result = SecStaticCodeCheckValidity(staticCodeRef, [], req)
if result == errSecSuccess {
print("Signature is trusted (anchor apple)")
} else {
print("Signature is NOT trusted by Apple (failed anchor check)")
}
}
var infoDict1: CFDictionary?
let signingStatus = SecCodeCopySigningInformation(staticCodeRef, SecCSFlags(rawValue: kSecCSSigningInformation), &infoDict1)
guard signingStatus == errSecSuccess, let info = infoDict1 as? [String: Any] else {
print("Failed to retrieve signing information.")
return
}
print("🔍 Signing Info for PID \(pid):")
for (key, value) in info.sorted(by: { $0.key < $1.key }) {
print("• \(key): \(value)")
}
}
If connection.setCodeSigningRequirement
does not works I plan to use above logic as backup.
Q: Please advise is there some setting required to be enabled or I have to sign code with some flags enabled.
Note: My app is not running in a Sandbox or Hardened Runtime, which I want.