How do I find the security session id for a pid?

I am building a somewhat-VPN-like system. I have a daemon that handles the networking and a couple of agents that interact with the logged-in user. The daemon and agent communicate via XPC.

I am trying to get this to work "smoothly" with fast-user-switching. Empirically, I find that the daemon can correlate XPC connection from different agents in the different login sessions via xpc_connection_get_asid(), which appears to be equivalent to the security session id, though it's not clear this this equivalence is always they case, nor will always be the case in the future. If I had a way to get the security session id for a pid, I would use xpc_connection_get_pid()

When the daemon gets a network connection I want to find the pid the connection is coming from (it can only be from the local machine) and figure out which security session that pid belongs to so that I can direct any necessary user interaction and permission checking to the agent in the security session from which the network request is coming. Finding the pid from the TCP port is arduous and inefficient, but doable. However, once I've found the pid, I don't know how to determine the security session id (or audit session id) that that pid is part of.

GetSessionInfo appears to permit me to get information about my own session id including my session id, or additional info about another session, if I already have that session id.

For my purposes, a viable alternative to being able to get the security session for a pid might be to be able to ask the question "Is this pid part of this security session?" since I expect to have agents in a small number of security sessions.

Getting the username of the pid is obviously doable, however this would mean that I would be unable to determine where a sudo'ed process was coming from (at least not without walking up the parent heirarchy). This feels dicey.

Am I missing something?

This feels dicey.

Yeah, much of what you’ve posted seems dicey. Specifically, anything based on PIDs is subject to PID wrap attacks and so you should avoid using PIDs where possible.

I also recommend that you not use data-specific calls like xpc_connection_get_asid and xpc_connection_get_pid. Rather, make the audit_token_t central to your work and then, if you need the other info, get that info from the audit token. See the various audit token APIs in <bsm/libbsm.h>, for example, audit_token_to_asid.

When the daemon gets a network connection I want to find the pid the connection is coming from

How does the daemon “get a network connection”. My general advice on this front is that you use a Network Extension provider for this sort of thing, and NE typically provides a way to go from a flow to an audit token. For example, NEFilterFlow has a sourceAppAuditToken property.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

this is a sort of VPN system

What exactly is a “sort of a VPN system”? This matters because the only supported way to create a VPN client on macOS is using an Network Extension provider. And NE providers have built-in support for this sort of thing, as I mentioned previously.

And, to be clear, by “supported” I mean “supported by DTS”. macOS is a relatively open system with a wealth of network infrastructure. Some of this is well documented, some of it less so, and some of it is only visible if you go rummaging in the Darwin open source. Historically macOS VPN clients used a variety of ad hoc techniques, and DTS would try to help them out with that. With the introduction of Network Extension providers on macOS 10.15, we stopped supported ad hoc VPN techniques because they are not compatible with DTS’s overall goal of helping developers create products that work today and continue working in the future.

If you’re building an actual VPN client, I recommend a packet tunnel provider or an app proxy provider, depending on what level you want to operate on. If your goal is to block traffic, at either the flow or packet level, create a content filter providers. For other stuff, a transparent proxy provider will usually fit the bill.

This works great with a single user logged on.

While I understand your concern about GUI login sessions, keep in mind that macOS also supports non-GUI login sessions (typically over SSH). It also allows code to run in a per-user context without any login session. Networking is fundamentally a system-wide service on the Mac.

But in a perfect world, I would like to know what login session a TCP connection is coming from

There isn’t a good way to get this information outside of the context of an NE provider.

Finding the pid from the TCP port is … doable.

Kinda. I suspect you’re playing games with libproc here (the library that underlies lsof) but there are lots of edge cases. At a minimum it’s possible to have a TCP connection with no associated PID (for example, an SMB connection coming out of the SMB VFS plug-in within the kernel) and a TCP connection with multiple associated PIDs (via descriptor passing).

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

How do I find the security session id for a pid?
 
 
Q