porting CCAPI to UNIX

Ken Raeburn raeburn at MIT.EDU
Fri May 18 00:18:57 EDT 2007


(No wonder I hadn't gotten any feedback on this... it's been sitting  
in my "drafts" folder still, unsent.  Oops.)

Based on a bunch of comments, it sounds like a process started at  
boot time is a good idea, but it should also be able to be started  
automatically by user processes.

So, a new proposal:

  * krb5.conf entry libdefaults/ccapi_path_template can specify a  
pathname template for the mode-700 directory holding the listening  
socket for a user.  Some substitutions are allowed to get the actual  
pathname; say, ${FOO} for environment variables, %u for decimal uid, % 
n for user account name, leading ~ for home directory.  (Q: Default  
to checking some environment variable that could be easily set at  
login time, as in Nico's krb5-agent idea?)

  * if such a pathname template is provided but the directory doesn't  
exist, the socket doesn't exist, or a connection can't be  
established, the server process is forked off with options telling it  
to run the service using that pathname.

  * if a pathname template isn't provided, libdefaults/ 
ccapi_path_server or a hard-coded value under $prefix or $exec_prefix  
indicates a UNIX-domain socket on which a server running as root  
should be listening; it gets sent a uid, and returns a pathname or an  
error.  If it returns a pathname, it's treated as above.  (By the  
time the pathname is sent, the server has created and is listening on  
that socket.)

  * if no server is listening on the server socket, it can be  
launched from the library.  Because it can be launched as the user  
and needs root privs for this path, it must be setuid root if used  
this way.  Which means in the former path, it needs to drop  
privileges before doing its work.  The socket pathname cannot be set  
by the user via $KRB5_CONFIG this way.  Possibly the client should be  
allowed to indicate the path it's expecting, so the server can just  
quit if that doesn't agree with the system config file or compiled-in  
path.

When the process is launched, fd 0 is a pipe connected to the parent  
process.  Closing this pipe indicates to the parent that it's time to  
try connecting; either the child process is listening on the UNIX- 
domain socket in question, or it's gotten an error, and isn't going  
to be able to.  So when the pipe gets closed, the parent process  
makes only one more attempt to access the UNIX-domain socket before  
giving up.  The parent could also time out (say, at 20 seconds) in  
case the server somehow hangs in launching.

It's a little messy having one server program do both per-user and  
monolithic approaches, but it lets us not require extra processes at  
boot time if they're not desired, and lets us do testing without root  
privileges.

Initially it may be simpler for the monolithic server to spawn  
subprocesses per uid instead of keeping everything in one process; I  
need to look a little deeper into the existing ccapi code.  If so,  
this should be transparent to the client, and changing it later  
shouldn't affect the protocol.  However, the core ccapi server code  
is going to eventually have to support multiple client uids not being  
able to see each others' credentials; if this support is there by the  
time this project is implemented, we can go with a single process.

The intent is that the server looks like it could be one program, and  
one process in the monolithic case, but if it's more convenient, it  
could first be implemented with multiple programs and processes under  
the covers, transparently to the client.

The library will launch processes, but we don't want to mess with  
application signal handling, so the library won't catch SIGCHLD.  On  
Solaris, as Nico suggested, we could use forkx or flags to  
posix_spawn to avoid having the signal sent at all -- if we have  
forkx; it appears to be a very recent addition, and the Solaris 10  
box in my office doesn't have it.  Otherwise, the application gets an  
extra SIGCHLD, just as it would if it uses popen() or system() etc.

As this would be a separate library from libkrb5, it could be  
replaced with something optimized for specific systems (e.g., using  
doors on Solaris) using the same ABI.

Ken



More information about the krbdev mailing list