gpg-agent and launchd

Stéphane Corthésy stephane at sente.ch
Fri Mar 21 18:32:07 CET 2008


Hi,

I'd like to see support of launchd in gpg-agent.

"launchd is a unified, open source service management framework for  
starting, stopping and managing daemons, programs and  
scripts" (wikipedia)

It is open-source <http://launchd.macosforge.org/>, under apache  
license, and is, under Darwin/MacOSX, responsible to launch all  
daemons and agents, based on different criteria, and will relaunch  
them if necessary. It replaces init, watchdogd, crond, etc.

Though apache license is incompatible with GPL, launchd is a system  
component on OSX (this is even the key component, with PID 1). That  
shouldn't cause problem, would it?


The goal is to have a well-integrated agent under MacOSX 10.5: the  
agent is launched when user logs in, is relaunched automatically in  
case of failure, and is stopped when user logs out. This is already  
achievable currently, but there are some limitations:
- as gpg-agent runs as a daemon, we cannot watchdog it, and relaunch  
it automatically, without an external watch dog process
- as we cannot make all user processes inherit from the environment  
variables of gpg-agent (user processes don't read the ~/.login or  
whatever), we need to stick with standard socket path, which works  
only if the home directory is mounted as a local file system
- when user logs out, gpg-agent is not terminated automatically


On a technical POV, a program launched by launchd must respect the  
following constraints (copied from launchd.plist(5) man page):

It MUST NOT:
            •   Call daemon(3).
            •   Do the moral equivalent of daemon(3) by calling  
fork(2) and
                have the parent process exit(3) or _exit(2).

It SHOULD NOT:
            •   Setup the user ID or group ID.
            •   Setup the working directory.
            •   chroot(2)
            •   setsid(2)
            •   Close "stray" file descriptors.
            •   Change stdio(3) to /dev/null.
            •   Setup resource limits with setrusage(2).
            •   Setup priority with setpriority(2).
            •   Ignore the SIGTERM signal.

It SHOULD:
            •   Launch on demand given criteria specified in the XML  
property
                list.  More information can be found later in this man  
page.
            •   Catch the SIGTERM signal.

Avoiding fork() is possible, as it is already done for Win32. Avoiding  
the chdir() too, as well as avoiding changing uig, gid, sid. I found  
no setrusage() nor setpriority(), at first look. SIGTERM is not  
ignored, and actually used by the code to terminate properly. I have  
no idea about the two other constraints, Close "stray" file  
descriptors, and Change stdio(3) to /dev/null.

Launching the agent on demand is unfortunately not possible: though we  
can configure launchd to create a secure socket, pass it through an  
environment variable, and launch gpg-agent only when the secure socket  
is being accessed, this is not possible for gpg-agent, because agent  
client processes (gpg) expect the GPG_AGENT_INFO to contain the socket  
path, the agent pid, and a version number. This cannot work for us, as  
the pid is unknown until the agent has been launched, and the created  
environment variable is only the socket path. Anyway, launching the  
agent at user's login works fine too.


I modified gpg-agent 2.0.8 to add support for launchd: I had to modify  
only gpg-agent.c.
I added a new command, --launchd, which is exclusive with --daemon and  
--server, and does currently the following:
- it creates sockets, like in daemon mode
- it does not fork - this is forbidden
- it does not run any program on the command line - this is forbidden
- it does not print the environment variables (though it might, maybe)
- it passes back to launchd the environment variables; launchd will  
make all user processes inherit of these variables
- it does not detach from tty (I don't know what this means and what  
are the consequences)
- it doesn't chdir("/"), but the launchd plist sets the working dir to  
"/", so it should be equivalent
- it removes the environment variables from launchd, when terminating

Is there any interest here to review and maybe include that code  
(available on demand) into gpg-agent?


Stéphane




More information about the Gnupg-devel mailing list