(re)configure a launchd created UNIX domain socket after Fast User Switching (on El Capitan)
Hello, I am using launchd to create a Unix domain socket /tmp/foobar.socket so that launchd starts my agent when someone connects to the sockets. It works fine except when Fast User Switching is involved. My problem is quite similar to the problem "Listening socket and fast user switching" [1] discussed on this mailing list in 2008. The difference is that I am using a UNIX domain socket and not a TCP socket. The problematic scenario is as follows: 1. User A logs in 2. User A can connect to the socket 3. User B logs in using the Fast User Switching 4. User B can connect to the socket 5. User B logs out 6. User A comes back and fast user switch to his session. Since user A does not _logs in_ again the socket is not changed/recreated and is still only usable by user B At this step user A gets: $ telnet /tmp/foobar.socket Trying /tmp/foobar.socket... /tmp/foobar.socket: Connection refused The socket is still present in /tmp/ but it belongs to user B and is no more usable but user A. What I would like is the ability for launchd to (re)configure the Unix domain socket each time a user authenticates to the console, either the first time or using the fast user switching method. - I use a UNIX domain socket so that only local processes can talk to the socket and use my agent. I don't want to open my agent to other computer on the network. - I use launchd to start my agent on request only. That is a very nice feature. I can't detect the user switching since my agent code is, most of the time, not running. - I can't use a different socket name per user since the client of my agent does not know who is currently logged. My client application is talking to the socket configured for whoever is logged at that time. My /Library/LaunchAgents/com.foobar.plist file contains: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" " http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>com.foobar</string> <key>ProgramArguments</key> <array> <string>/usr/local/lib/foobar_exe</string> </array> <key>Sockets</key> <dict> <key>Listeners</key> <dict> <key>SockPathName</key> <string>/tmp/foobar.socket</string> </dict> </dict> <key>ProcessType</key> <string>Interactive</string> </dict> </plist> Does launchd provides a solution to my problem? Should I open a bug at Apple to ask for this new feature in launchd? Thanks [1] https://lists.macosforge.org/pipermail/launchd-dev/2008-May/000298.html -- Dr. Ludovic Rousseau
What would happen if there were multiple active users at the same time (like with Screen Sharing, where the local GUI user and a remote user can both have active sessions)? Or with a local GUI user and another user SSH’d in? -Greg
On Feb 25, 2016, at 5:43 AM, Ludovic Rousseau <ludovic.rousseau@gmail.com> wrote:
Hello,
I am using launchd to create a Unix domain socket /tmp/foobar.socket so that launchd starts my agent when someone connects to the sockets.
It works fine except when Fast User Switching is involved.
My problem is quite similar to the problem "Listening socket and fast user switching" [1] discussed on this mailing list in 2008. The difference is that I am using a UNIX domain socket and not a TCP socket.
The problematic scenario is as follows: 1. User A logs in 2. User A can connect to the socket
3. User B logs in using the Fast User Switching 4. User B can connect to the socket 5. User B logs out
6. User A comes back and fast user switch to his session. Since user A does not _logs in_ again the socket is not changed/recreated and is still only usable by user B
At this step user A gets: $ telnet /tmp/foobar.socket Trying /tmp/foobar.socket... /tmp/foobar.socket: Connection refused
The socket is still present in /tmp/ but it belongs to user B and is no more usable but user A.
What I would like is the ability for launchd to (re)configure the Unix domain socket each time a user authenticates to the console, either the first time or using the fast user switching method.
- I use a UNIX domain socket so that only local processes can talk to the socket and use my agent. I don't want to open my agent to other computer on the network. - I use launchd to start my agent on request only. That is a very nice feature. I can't detect the user switching since my agent code is, most of the time, not running. - I can't use a different socket name per user since the client of my agent does not know who is currently logged. My client application is talking to the socket configured for whoever is logged at that time.
My /Library/LaunchAgents/com.foobar.plist file contains:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd <http://www.apple.com/DTDs/PropertyList-1.0.dtd>"> <plist version="1.0"> <dict> <key>Label</key> <string>com.foobar</string> <key>ProgramArguments</key> <array> <string>/usr/local/lib/foobar_exe</string> </array> <key>Sockets</key> <dict> <key>Listeners</key> <dict> <key>SockPathName</key> <string>/tmp/foobar.socket</string> </dict> </dict> <key>ProcessType</key> <string>Interactive</string> </dict> </plist>
Does launchd provides a solution to my problem?
Should I open a bug at Apple to ask for this new feature in launchd?
Thanks
[1] https://lists.macosforge.org/pipermail/launchd-dev/2008-May/000298.html <https://lists.macosforge.org/pipermail/launchd-dev/2008-May/000298.html>
-- Dr. Ludovic Rousseau _______________________________________________ launchd-dev mailing list launchd-dev@lists.macosforge.org https://lists.macosforge.org/mailman/listinfo/launchd-dev
2016-02-25 15:57 GMT+01:00 Gregory Neagle <gregneagle@mac.com>:
What would happen if there were multiple active users at the same time (like with Screen Sharing, where the local GUI user and a remote user can both have active sessions)? Or with a local GUI user and another user SSH’d in?
That is a very good point. I am trying to solve a problem with a tokend (part of CDSA) used by Safari and Mail. So a SSH session (text only) is not an issue for me. A remote user starting a graphical session would be a problem. I will check that to see what happens in this case. I think I can consider this as a known limitation of my solution. Thanks -- Dr. Ludovic Rousseau
Ludovic, If possible, I would recommend using XPC for this purpose. Rather than managing the permissions of a socket on-disk, the MachServices names registered by your agent would be in user-specific namespaces such that this collision never happens. If that is not possible, then I would recommend taking a look at the SecureSocketForKey option. Instead of specifying the path name upfront, launchd will put the socket at a random path and then set that path as the value for an environment variable (which you name in the value for SecureSocketForKey). launchd then assures that all jobs within the same context as your agent get that environment variable so they can rendezvous with your agent. So for example, if your socket dictionary was <key>Listeners</key> <dict> <key>SecureSocketForKey</key> <string>MY_KEY</string> </dict> other processes would be able to just do a getenv("MY_KEY") to get the path to the socket and connect to it. This should achieve the user-based isolation you want with sockets. Though as I said before, XPC is a much more natural mechanism for IPC on OS X, so use that if it's a practical option for you. -damien
On 25 Feb, 2016, at 05:43, Ludovic Rousseau <ludovic.rousseau@gmail.com> wrote:
Hello,
I am using launchd to create a Unix domain socket /tmp/foobar.socket so that launchd starts my agent when someone connects to the sockets.
It works fine except when Fast User Switching is involved.
My problem is quite similar to the problem "Listening socket and fast user switching" [1] discussed on this mailing list in 2008. The difference is that I am using a UNIX domain socket and not a TCP socket.
The problematic scenario is as follows: 1. User A logs in 2. User A can connect to the socket
3. User B logs in using the Fast User Switching 4. User B can connect to the socket 5. User B logs out
6. User A comes back and fast user switch to his session. Since user A does not _logs in_ again the socket is not changed/recreated and is still only usable by user B
At this step user A gets: $ telnet /tmp/foobar.socket Trying /tmp/foobar.socket... /tmp/foobar.socket: Connection refused
The socket is still present in /tmp/ but it belongs to user B and is no more usable but user A.
What I would like is the ability for launchd to (re)configure the Unix domain socket each time a user authenticates to the console, either the first time or using the fast user switching method.
- I use a UNIX domain socket so that only local processes can talk to the socket and use my agent. I don't want to open my agent to other computer on the network. - I use launchd to start my agent on request only. That is a very nice feature. I can't detect the user switching since my agent code is, most of the time, not running. - I can't use a different socket name per user since the client of my agent does not know who is currently logged. My client application is talking to the socket configured for whoever is logged at that time.
My /Library/LaunchAgents/com.foobar.plist file contains:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd <http://www.apple.com/DTDs/PropertyList-1.0.dtd>"> <plist version="1.0"> <dict> <key>Label</key> <string>com.foobar</string> <key>ProgramArguments</key> <array> <string>/usr/local/lib/foobar_exe</string> </array> <key>Sockets</key> <dict> <key>Listeners</key> <dict> <key>SockPathName</key> <string>/tmp/foobar.socket</string> </dict> </dict> <key>ProcessType</key> <string>Interactive</string> </dict> </plist>
Does launchd provides a solution to my problem?
Should I open a bug at Apple to ask for this new feature in launchd?
Thanks
[1] https://lists.macosforge.org/pipermail/launchd-dev/2008-May/000298.html <https://lists.macosforge.org/pipermail/launchd-dev/2008-May/000298.html>
-- Dr. Ludovic Rousseau _______________________________________________ launchd-dev mailing list launchd-dev@lists.macosforge.org https://lists.macosforge.org/mailman/listinfo/launchd-dev
Hello Damien, I am not sure that XPC will help me here. Maybe I need to describe the problem I try to solve :-) I am working on a tokend component. This tokend component is part of CDSA architecture and is used to interact with a smart card. CDSA is deprecated by Apple since OS X Lion in 2011 [1] but is still usable and have not yet been replaced by Apple by something else. The tokend component is executed by the user "_tokend". I can interact with it using the Keychain Access application or Safari or Mail. When needed a component (I guess part of CDSA) asks the user to enter the smart card secret PIN code. The PIN code is then transferred to my tokend component so I can send it to the smart card. This simple use case works fine. In some cases (depending on the smart card configuration) my tokend needs to ask the user for the PIN again (or for a different PIN value). My tokend component is running as user _tokend, not as the logged in user and has no access to the Cocoa framework to display a dialog box. I tried to use Cocoa from the tokend but the GUI is not behaving correctly. So I need a way to communicate from a process running as _tokend to a process with access to the graphical interface, a process started as the logged in user. My solution using a UNIX socket and launchd works fine. An application is started as the logged in user when needed and this application can display windows and interact with the user. The limitation is that my solution does not work when 2 users are logged in at the same time, either using fast user switching or over the network. For what I read about XPC it has been designed as an isolation mechanism. An XPC service has very limited privileges. I imagine that using Cocoa is not part of the allowed privileges. Exact? Bye [1] http://ludovicrousseau.blogspot.com/2011/08/mac-os-x-lion-and-tokend.html 2016-02-25 17:27 GMT+01:00 Damien Sorresso <dsorresso@apple.com>:
Ludovic,
If possible, I would recommend using XPC for this purpose. Rather than managing the permissions of a socket on-disk, the MachServices names registered by your agent would be in user-specific namespaces such that this collision never happens.
If that is not possible, then I would recommend taking a look at the SecureSocketForKey option. Instead of specifying the path name upfront, launchd will put the socket at a random path and then set that path as the value for an environment variable (which you name in the value for SecureSocketForKey). launchd then assures that all jobs within the same context as your agent get that environment variable so they can rendezvous with your agent. So for example, if your socket dictionary was
<key>Listeners</key> <dict> <key>SecureSocketForKey</key> <string>MY_KEY</string> </dict>
other processes would be able to just do a getenv("MY_KEY") to get the path to the socket and connect to it. This should achieve the user-based isolation you want with sockets. Though as I said before, XPC is a much more natural mechanism for IPC on OS X, so use that if it's a practical option for you. -damien
On 25 Feb, 2016, at 05:43, Ludovic Rousseau <ludovic.rousseau@gmail.com> wrote:
Hello,
I am using launchd to create a Unix domain socket /tmp/foobar.socket so that launchd starts my agent when someone connects to the sockets.
It works fine except when Fast User Switching is involved.
My problem is quite similar to the problem "Listening socket and fast user switching" [1] discussed on this mailing list in 2008. The difference is that I am using a UNIX domain socket and not a TCP socket.
The problematic scenario is as follows: 1. User A logs in 2. User A can connect to the socket
3. User B logs in using the Fast User Switching 4. User B can connect to the socket 5. User B logs out
6. User A comes back and fast user switch to his session. Since user A does not _logs in_ again the socket is not changed/recreated and is still only usable by user B
At this step user A gets: $ telnet /tmp/foobar.socket Trying /tmp/foobar.socket... /tmp/foobar.socket: Connection refused
The socket is still present in /tmp/ but it belongs to user B and is no more usable but user A.
What I would like is the ability for launchd to (re)configure the Unix domain socket each time a user authenticates to the console, either the first time or using the fast user switching method.
- I use a UNIX domain socket so that only local processes can talk to the socket and use my agent. I don't want to open my agent to other computer on the network. - I use launchd to start my agent on request only. That is a very nice feature. I can't detect the user switching since my agent code is, most of the time, not running. - I can't use a different socket name per user since the client of my agent does not know who is currently logged. My client application is talking to the socket configured for whoever is logged at that time.
My /Library/LaunchAgents/com.foobar.plist file contains:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" " http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>com.foobar</string> <key>ProgramArguments</key> <array> <string>/usr/local/lib/foobar_exe</string> </array> <key>Sockets</key> <dict> <key>Listeners</key> <dict> <key>SockPathName</key> <string>/tmp/foobar.socket</string> </dict> </dict> <key>ProcessType</key> <string>Interactive</string> </dict> </plist>
Does launchd provides a solution to my problem?
Should I open a bug at Apple to ask for this new feature in launchd?
Thanks
[1] https://lists.macosforge.org/pipermail/launchd-dev/2008-May/000298.html
-- Dr. Ludovic Rousseau _______________________________________________ launchd-dev mailing list launchd-dev@lists.macosforge.org https://lists.macosforge.org/mailman/listinfo/launchd-dev
-- Dr. Ludovic Rousseau
On 1 Mar 2016, at 10:44, Ludovic Rousseau <ludovic.rousseau@gmail.com> wrote:
So I need a way to communicate from a process running as _tokend to a process with access to the graphical interface, a process started as the logged in user.
Do you care whether this GUI process is running all the time? If not, you can just create a launchd agent and have it connect to your daemon. When the daemon needs help, it can send a message to the appropriate connected agent (or send a message to /all/ the connected agents). If you want the agents to /not/ be running all the time you can configure the agents to listen for a Darwin notification (see <x-man-page://3/notify> and <x-man-page://3/xpc_events>). The daemon can then post that notification when it needs help. This will launch the agents, and they can then connect to the daemon as above. Regardless, you can use XPC (or the higher-level NSXPCConnection) to communicate between your daemon and agents. An launchd daemon can advertise an XPC service via a MachServices property in the launchd property list. Share and Enjoy -- Quinn "The Eskimo!" <http://www.apple.com/developer/> Apple Developer Relations, Developer Technical Support, Core OS/Hardware
participants (4)
-
Damien Sorresso
-
Gregory Neagle
-
Ludovic Rousseau
-
Quinn "The Eskimo!"