Posts

Post not yet marked as solved
5 Replies
804 Views
What's the best/correct/current way of checking if a SecKey (or any keychain item) is allowed to be accessed (decrypted) by the current process? This would apply to signing or decrypting for a private key, or the data/contents of a password item (or key). Given the number of APIs deprecated, and that some of the listed interaction mechanisms don't seem to work (FB11153260), I was wondering if there was some SecItemCopyMatching magic, or something related to LAContext. In this use-case the SecKey is provided to this code, or it may fall back to enumeration by hostname (common name), so a persistent reference doesn't apply (though I realize that's a best practice). It looks like kSecUseAuthenticationUI doesn't work, and neither does kSecUseAuthenticationContext with interactionNotAllowed set to false. The deprecated SecKeychainSetUserInteractionAllowed still works though. In the past it was possible to enumerate the ACLs of an item using SecKeychainItemCopyAccess, but there doesn't seem to be an alternative. I was hoping it was possible to use kSecUseItemList with one of the kSecUseAuthentication* options in SecItemCopyMatching to return an error or an empty list, but that doesn't seem to work. Same with kSecMatchItemList. LAContext itself has a way to evaluate operations, but not with reference to a particular item. Either examination of the item (e.g. ACLs), evaluation of a policy (can sign?), or failure from something like SecItemCopyMatching would be fine, but it must work with interaction suppressed.
Posted
by TyngJJ.
Last updated
.
Post not yet marked as solved
3 Replies
791 Views
When creating a framer which will mark ready, we can't seem to get a reply to the first outgoing message sent by the framer, e.g. of the style: < 220 Service ready for new user.\r\n > AUTH TLS\r\n < 234 Command AUTH okay; starting TLS connection.\r\n The incoming message starting 234 is never received by the framer unless it marks ready right after sending the AUTH line. It looks like this is intentional but we can't understand why this is prevented given the framer should probably check the reply before attempting to prepend e.g. a TLS protocol on the stack (may depend on return code). The dependency seems to be that marking ready will allow the next read, but prevent prepending, and prepending will immediately trigger the TLS handshake, and it will consume the 234 line. It looks like "pass through" can be called any time, before or after, but that requires another protocol on the stack to do the work. Do we need to have one framer read the first message and send one message then mark ready and pass through, prepend another identical framer to read the next message then make the decision to prepend TLS, then prepend again for the "decrypted" framer to read the actual application protocol? We're doing this in C/ObjC, but I figured the Swift terminology might help in the title. Apologies if this was already asked somewhere, I couldn't find a good match.
Posted
by TyngJJ.
Last updated
.
Post not yet marked as solved
4 Replies
940 Views
We've recently noticed an issue on our new MacStudios where calls to psort_r(3) stall forever. We haven't changed our HPC (particle simulation) code at all, and sampling the app shows psort_r is stuck in dispatch_group_wait(3). Taking the code from Libc 1439.141.1, we've assembled our own implementation which allows us to pass a dispatch_queue_t, dispatch_group_t, and specify a wait time. After 10 seconds (a very long time in our case) the call returns with a non-zero exit code and shows the group and queue are in agreement: four additional blocks are waiting to dispatch, but haven't. This still takes more than two hours of simulation to achieve, where calls to psort_r must be succeeding to make forward progress. Prior to this code change we've seen dispatch_group_wait stuck for hours. What else could we do to diagnose/debug this? We only see it on our M1 Ultra MacStudios, and the comparator passed to psort_r is simple C code (constant time). FB10893202
Posted
by TyngJJ.
Last updated
.
Post not yet marked as solved
3 Replies
1.1k Views
Looks like dnsextd(8) was removed from macOS in 10.15 Catalina, and building from source isn't easy. I used the attached patch to build mDNSResponder 1310.140.1, which removes unused functions except for setTrafficClass which is unused by the target (it passes mDNSFalse for useBackgroundTraffic). We're planning to use this as a frontend to BIND 9.18.3 with an external daemon to verify TSIG for dynamic updates. With MDM we should be able to easily provision new TSIG keys remotely on servers, then communicate them out-of-band to the daemon and (hopefully) have the process work almost automatically. I have heard only RC4 is supported in released versions of macOS, and the implementation is broken in macOS Monterey. dnsextd.txt Comments welcome
Posted
by TyngJJ.
Last updated
.
Post not yet marked as solved
0 Replies
778 Views
Is there a simple way to create an NSFontCollection based on NSFontDescriptor querying to gather all installed/available fonts with a MATH table? It doesn't look like there's an attribute for that, but I don't know how else to search other than correlating with features like ssty, dtls, and flac.
Posted
by TyngJJ.
Last updated
.
Post not yet marked as solved
7 Replies
3.4k Views
I've tried to find explicit documentation for the role to select when creating an API key for use withxcrun altool --notarize-app --apiKeyBut only found a discussion like Using an API Key with iTMSTransporter. Should it always be App Manager, or is there a less-priviledged one for this task? Notarization doesn't seem like it would require significant access.
Posted
by TyngJJ.
Last updated
.
Post not yet marked as solved
1 Replies
1.3k Views
Have DriverKit entitlement decisions started being issued? We filled in the form weeks ago and haven't received a response of any kind. We already had a kext entitlement, so I was hoping the request would be a formality.
Posted
by TyngJJ.
Last updated
.
Post not yet marked as solved
0 Replies
691 Views
I've found Console.app much harder to use in recent years, and one of the issues is the firehose of data is much more difficult to examine when you don't know what you're looking for, especially if you have to turn on debug and info. As an example of a tool, I'm posting a script I wrote to gather likely subsystem/category names from other binaries. It's crude, but does a decent job when you're not sure where to start #!/usr/bin/swift import Foundation extension Process { &#9;&#9;class func launchedForLines(url: URL, args: [String], block: (String) -> Void) { &#9;&#9;&#9;&#9;let proc = Process(), pipe = Pipe(), eol = Data([0x0A]) &#9;&#9;&#9;&#9;proc.executableURL = url &#9;&#9;&#9;&#9;proc.arguments = args &#9;&#9;&#9;&#9;proc.standardOutput = pipe &#9;&#9;&#9;&#9;proc.launch() &#9;&#9;&#9;&#9;let output = pipe.fileHandleForReading &#9;&#9;&#9;&#9;var buffer = Data(capacity: Int(LINE_MAX)), chunk = output.availableData &#9;&#9;&#9;&#9;while !chunk.isEmpty { &#9;&#9;&#9;&#9;&#9;&#9;buffer.append(chunk) &#9;&#9;&#9;&#9;&#9;&#9;while let range = buffer.range(of: eol) { &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;let slice = buffer[0..<range.lowerBound] &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;buffer.replaceSubrange(0..<range.upperBound, with: Data()) &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;if let line = String(data: slice, encoding: .utf8) { &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;block(line) &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;&#9;&#9;chunk = output.availableData &#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;proc.terminate() &#9;&#9;} } struct Log : Hashable, Equatable { &#9;&#9;let subsystem:String, category:String } func find_logs(url: URL) -> [Log]? { &#9;&#9;let literal = "literal pool for: \"", hold = "HOLD" &#9;&#9;var ring = [hold, hold], idx = false, logs = Set&lt;Log&gt;() &#9;&#9;Process.launchedForLines(url: URL(fileURLWithPath: "/usr/bin/otool", isDirectory: false), args: ["-tV", url.path], block: { (line) in &#9;&#9;&#9;&#9;if let range = line.range(of: literal) { &#9;&#9;&#9;&#9;&#9;&#9;let frag = line[range.upperBound..<line.index(before: line.endIndex)] &#9;&#9;&#9;&#9;&#9;&#9;ring[idx ? 1 : 0] = String(frag) &#9;&#9;&#9;&#9;&#9;&#9;idx = !idx &#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;else if line.range(of: "_os_log_create", options: .literal) != nil { &#9;&#9;&#9;&#9;&#9;&#9;let sub = ring[idx ? 1 : 0], cat = ring[idx ? 0 : 1] &#9;&#9;&#9;&#9;&#9;&#9;if sub != hold &amp;&amp; cat != hold &amp;&amp; sub.range(of: ".", options: .literal) != nil { &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;logs.insert(Log(subsystem: sub, category: cat)) &#9;&#9;&#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;&#9;&#9;ring = [hold, hold] &#9;&#9;&#9;&#9;} &#9;&#9;}) &#9;&#9;return logs.isEmpty ? nil : Array(logs) } func check_mach(url: URL) -> Bool { &#9;&#9;guard let handle = try? FileHandle(forReadingFrom: url) else { &#9;&#9;&#9;&#9;return false &#9;&#9;} &#9;&#9;let size = MemoryLayout.size(ofValue: MH_MAGIC), magic = handle.readData(ofLength: size) &#9;&#9;try? handle.close() &#9;&#9;return magic.count == size &amp;&amp; [MH_MAGIC, MH_MAGIC_64, FAT_CIGAM, FAT_CIGAM_64].contains(magic.withUnsafeBytes({ $0.load(as: UInt32.self) })) } func enumerate(url: URL, block: (URL, URLFileResourceType) -> Void) { &#9;&#9;guard let type = try? url.resourceValues(forKeys: [.fileResourceTypeKey]).fileResourceType else { &#9;&#9;&#9;&#9;return &#9;&#9;} &#9;&#9;block(url, type) &#9;&#9;if (type == .directory) { &#9;&#9;&#9;&#9;_ = (try? FileManager.default.contentsOfDirectory(at: url, includingPropertiesForKeys: [.fileResourceTypeKey], options: []))?.map({ enumerate(url: $0, block: block) }) &#9;&#9;} } let args = ProcessInfo().arguments guard let base = args.count > 1 ? URL(fileURLWithPath: args[1]) : nil else { &#9;&#9;print("Specify exactly one argument, the path to search") &#9;&#9;exit(1) } enumerate(url: base) { (url, type) in &#9;&#9;autoreleasepool { &#9;&#9;&#9;&#9;if type == .regular &amp;&amp; check_mach(url: url), let logs = find_logs(url: url) { &#9;&#9;&#9;&#9;&#9;&#9;print("Found binary \(url.path)") &#9;&#9;&#9;&#9;&#9;&#9;_ = logs.map({ print("Subsystem: \($0.subsystem) Category: \($0.category)") }) &#9;&#9;&#9;&#9;} &#9;&#9;} }
Posted
by TyngJJ.
Last updated
.
Post not yet marked as solved
5 Replies
1.1k Views
This is for macOS Cocoa apps. I've been using NSPortNameServer until its deprecation to claim a "name" for simple IPC that's automatically destroyed when the process that called -registerPort: exits for any reason. The purpose is to guard other processes using the same framework from clobbering each other trying to the the same thing (just the TASK for discussion purposes) when more than one are running at the same time. There's no information exchanged except to call "dibs" on this TASK, and ideally the solution we move to also works with sandboxing.I've avoided filesystem semantics because files/directories/named semaphores all persist if the process that created them dies, which will litter that namespace, and most don't provide an efficient way of detecting whether the process that created them is still alive.The processes don't need to exchange any data at all, just for one of them (the first to claim the privilege) to handle TASK during its lifetime. The other processes continue to receive the event notifications which would trigger the TASK, so if the claimant dies the next to respond will take the claim immediately. It's also important that this claim only be held session-wide, not machine-wide.It doesn't look like notifyd, sem_open, and others provide this particular semantic, and the closest I got was an NSProgress published nominally to an aribtrary file/directory, but that seems more like API abuse, as would NSFileCoordinator (though that at least is closer). I don't see how holding this particular claim could be considered a security risk, so I would hope it could also work with sandboxing (e.g. not require an app group, etc).
Posted
by TyngJJ.
Last updated
.
Post marked as solved
5 Replies
1.5k Views
I've got a kext that worked fine on Mojave, now it won't load at all, saying:$ kextutil -tn kext kxld[kext]: The following symbols are unresolved for this kext: kxld[kext]: IOCatalogue::addDrivers(OSArray*, bool) kxld[kext]: IOCatalogue::removeDrivers(OSDictionary*, bool) kxld[kext]: IOCatalogue::startMatching(OSDictionary*) Link failed (error code 5). Check library declarations for your kext with kextlibs(8).As far as I know these symbols are still declared in IOCatalogue.h in the Kernel framework, and while kexts are deprecated, they're still technically allowed in Catalina? Posted to FB6142774 (btw, what's the URL format for feedbacks?)
Posted
by TyngJJ.
Last updated
.