Douglas E. Engert
2004-Jan-26 17:21 UTC
OpenSSH, OpenAFS, Heimdal Kerberos and MIT Kerberos
Rather then implementing kafs in MIT Kerberos, I would like to suggest an alternative which has advantages to all parties. The OpenSSH sshd needs to do two things: (1) sets a PAG in the kernel, (2) obtains an AFS token storing it in the kernel. It can use the Kerberos credentials either obtained via GSSAPI delegation, PAM or other kerberos login code in the sshd. The above two actions can be accomplished by a separate process, which can be forked and execd by the sshd and passed the environment which may have a KREB5CCNAME pointing at the Kerberos ticket cache Other parameters such as the home directory could also be passed. This would then allow simple code in OpenSSH that does not depend on OpenAFS, Hiemdal or MIT code to fork/exec the process that does all the work. This would be called by the process that would eventially become the user's shell process and is run as the user. OpenSSH could be built on systems that may or may not have AFS installed and run on a system with or without AFS. The decision is based on the existence of the executable and any options in sshd_config. In its simplest form, all that is needed is: system("/usr/ssh/libexec/aklog -setpag") This is a little over simplified as there should be a test if the executable exists, processing of some return codes, making sure the environment is set, setting some time limit. etc. But the point is there is no compile dependence on OpenAFS, MIT or Hiemdal by the OpenSSH sshd, and any failure of the process will not effect the sshd. We have been using something like this for years which issues a syscall to set a PAG for the current process, then fork/exec ak5log. Our current mode to OpenSSH in session.c is as simple as: krb5_afs_pag_env(NULL, env); It is currently built with the MIT Kerberos code for historic reasons, but could be seperate as it has no real dependency on the MIT code. I would hope that the members of the OpenSSH community who use OpenAFS, Hiemdal and/or MIT could agree on a simple command line interface that would encourage the builders of OpenSSH to always have this enabled. -- Douglas E. Engert <DEEngert at anl.gov> Argonne National Laboratory 9700 South Cass Avenue Argonne, Illinois 60439 (630) 252-5444
Jeffrey Altman
2004-Jan-26 17:34 UTC
[OpenAFS-devel] OpenSSH, OpenAFS, Heimdal Kerberos and MIT Kerberos
Douglas E. Engert wrote:>In its simplest form, all that is needed is: > > system("/usr/ssh/libexec/aklog -setpag") > >You would probably want this to be a configurable option in the sshd configuration file as opposed to have a fixed name, location and options which are set at compile time. Jeffrey Altman -------------- next part -------------- A non-text attachment was scrubbed... Name: smime.p7s Type: application/x-pkcs7-signature Size: 3427 bytes Desc: S/MIME Cryptographic Signature Url : http://lists.mindrot.org/pipermail/openssh-unix-dev/attachments/20040126/0381fe3d/attachment.bin
Douglas E. Engert
2004-Jan-26 17:43 UTC
[OpenAFS-devel] OpenSSH, OpenAFS, Heimdal Kerberos and MIT Kerberos
Jeffrey Altman wrote:> > Douglas E. Engert wrote: > > >In its simplest form, all that is needed is: > > > > system("/usr/ssh/libexec/aklog -setpag") > > > > > You would probably want this to be a configurable option in the sshd > configuration file > as opposed to have a fixed name, location and options which are set at > compile time.Yes, I would assume the location could be set like the sftpd location is set. Subsystem sftp /krb5/libexec/sftp-server I was trying to show the simplist example.> Jeffrey Altman-- Douglas E. Engert <DEEngert at anl.gov> Argonne National Laboratory 9700 South Cass Avenue Argonne, Illinois 60439 (630) 252-5444
Andrei Maslennikov
2004-Jan-26 18:43 UTC
[OpenAFS-devel] OpenSSH, OpenAFS, Heimdal Kerberos and MIT Kerberos
We have implemented the strategy similar to the one that Douglas suggested in his posting. In our case (Heimdal) we allow user to login using his/her K5 password and then call Heimdal "afslog" inside session.c: system("/usr/sshutils/sbin/afslog >/dev/null 2>&1"); A small complementary trick (sshd is invoked via inetd/xinetd with "-i" flag from within the pagsh wrapper) allows the token to be obtained automatically in a brand-new pagsh. All this works with the protocol 2, and users obtain both K5 tickets and PAG-based tokens upon login. Apart from just one extra system call, no code hacking is needed for OpenSSH. What we were yet unable to achieve is the further K5 credentials forwarding in case of login via the K5 password. What happens is the following: 1) ssh to host A, login with K5 password (and obtain a PAG-based token) 2) from host A, ssh to host B, login w/o pw (this time with GSSAPI) 3) inside host B: no K5 creds forwarded from host A, no token. A possible workaround would be to re-authenticate automatically with GSSAPI right after the successful K5 password login (using the just-obtained K5 creds), but it might be tricky to implement. There is even a comment in the auth2.c ("/* XXX todo: check if multiple auth methods are needed */), but nobody ever went further. If this would work, the GSSAPI creds would be stored on host A and then presumably forwarded to the host B during the GSSAPI login (and hence the AFS token would be obtained there automatically). I.e. it could become possible to type in the password only one time, and then navigate with ssh between enabled machines without password - all this while preserving K5 creds and automatically obtaining AFS tokens. Andrei. On Mon, 26 Jan 2004, Douglas E. Engert wrote:> Rather then implementing kafs in MIT Kerberos, I would like to suggest > an alternative which has advantages to all parties. > > The OpenSSH sshd needs to do two things: > (1) sets a PAG in the kernel, > (2) obtains an AFS token storing it in the kernel. > > It can use the Kerberos credentials either obtained via GSSAPI > delegation, PAM or other kerberos login code in the sshd. > > The above two actions can be accomplished by a separate process, which > can be forked and execd by the sshd and passed the environment which may > have a KREB5CCNAME pointing at the Kerberos ticket cache Other > parameters such as the home directory could also be passed. > > > This would then allow simple code in OpenSSH that does not depend on > OpenAFS, Hiemdal or MIT code to fork/exec the process that does all the > work. This would be called by the process that would eventially become > the user's shell process and is run as the user. > > OpenSSH could be built on systems that may or may not have AFS installed > and run on a system with or without AFS. The decision is based on the > existence of the executable and any options in sshd_config. > > In its simplest form, all that is needed is: > > system("/usr/ssh/libexec/aklog -setpag") > > This is a little over simplified as there should be a test if the > executable exists, processing of some return codes, making sure the > environment is set, setting some time limit. etc. But the point is there > is no compile dependence on OpenAFS, MIT or Hiemdal by the OpenSSH sshd, > and any failure of the process will not effect the sshd. > > > > We have been using something like this for years which issues a syscall > to set a PAG for the current process, then fork/exec ak5log. Our > current mode to OpenSSH in session.c is as simple as: > > krb5_afs_pag_env(NULL, env); > > It is currently built with the MIT Kerberos code for historic reasons, > but could be seperate as it has no real dependency on the MIT code. > > I would hope that the members of the OpenSSH community who use OpenAFS, > Hiemdal and/or MIT could agree on a simple command line interface that > would encourage the builders of OpenSSH to always have this enabled. > >
I don't disagree with your proposal at all. Sounds good. It should make it easier to fix/change things in the future. But. . . Isn't the reason this keeps coming up that AFS client doesn't (can't?) behave like a normal Kerberos application and just get it's own service ticket when it needs one (based on an existing tgt)? The real reason this doesn't happen is that tickets are stored in a file in /tmp, but it's a different set of file system code inside the kernel that would need to access it to request the service ticket. Can't we figure a way to just make the kernel module get the service ticket (token) automatically, or fail if there is no tgt? That would make the whole problem go away and AFS would no longer need the special attention it does now. I note that on MacOS X tickets are stored in a MACH "security context" which acts a lot like a PAG. Furthermore it's accessible inside the kernel. Doesn't Windows have some similar in-memory storage mechanism? Has anyone thought about how congruent PAGs and terminal sessions are? I think X11 defined the latter, and Kerberos has tried to tie in to them rather than import the PAG concept. At 11:21 AM -0600 1/26/04, Douglas E. Engert wrote:>Rather then implementing kafs in MIT Kerberos, I would like to >suggest an alternative which has advantages to all parties. > >The OpenSSH sshd needs to do two things: > (1) sets a PAG in the kernel, > (2) obtains an AFS token storing it in the kernel. > >It can use the Kerberos credentials either obtained via GSSAPI >delegation, PAM or other kerberos login code in the sshd. > >The above two actions can be accomplished by a separate process, >which can be forked and execd by the sshd and passed the environment >which may have a KREB5CCNAME pointing at the Kerberos ticket cache >Other parameters such as the home directory could also be passed. > > >This would then allow simple code in OpenSSH that does not depend >on OpenAFS, Hiemdal or MIT code to fork/exec the process that does >all the work. This would be called by the process that would >eventially become the user's shell process and is run as the user. > >OpenSSH could be built on systems that may or may not have AFS >installed and run on a system with or without AFS. The decision >is based on the existence of the executable and any options >in sshd_config. > >In its simplest form, all that is needed is: > > system("/usr/ssh/libexec/aklog -setpag") > >This is a little over simplified as there should be a test if the >executable exists, processing of some return codes, making sure the >environment is set, setting some time limit. etc. But the point is >there is no compile dependence on OpenAFS, MIT or Hiemdal by the >OpenSSH sshd, and any failure of the process will not effect the sshd. > > > >We have been using something like this for years which issues a >syscall to set a PAG for the current process, then fork/exec ak5log. >Our current mode to OpenSSH in session.c is as simple as: > > krb5_afs_pag_env(NULL, env); > >It is currently built with the MIT Kerberos code for historic reasons, >but could be seperate as it has no real dependency on the MIT code. > >I would hope that the members of the OpenSSH community who use OpenAFS, >Hiemdal and/or MIT could agree on a simple command line interface that >would encourage the builders of OpenSSH to always have this enabled. > >-- > > Douglas E. Engert <DEEngert at anl.gov> > Argonne National Laboratory > 9700 South Cass Avenue > Argonne, Illinois 60439 > (630) 252-5444-- The opinions expressed in this message are mine, not those of Caltech, JPL, NASA, or the US Government. Henry.B.Hotz at jpl.nasa.gov, or hbhotz at oxy.edu
I'd like to second Doug's idea as a potential solution for OpenSSH at least.
Douglas E. Engert
2004-Jan-30 17:47 UTC
OpenSSH, OpenAFS, Heimdal Kerberos and MIT Kerberos
On Monday, I proposed a alternative method of obtaining and AFS PAG and token when used with OpenSSH or any other deamon. I now have a test working using openssh-snap-20040122. This relies on an external program referred to as get-afs-token which accepts at least two parameters: -setpag - Use the AFS Kernel mods to set the AFS PAG of the parent process. -path <directory> - Get a AFS token for the cell containing this directory. The get-afs-token program would be provided by the OpenAFS or Kerberos communities, and could be a link to aklog, afslog or gssklog. I have tried this with my version of aklog, called ak5log, and with gssklog. The aklog already accepted these parameters and afslog only need a minor addition as did the gssklog. Here is the sample code used with OpenSSH. Note that the get_afs_token routine does not require any AFS or Kerberos header files. --- ./,session.c Tue Jan 20 18:00:46 2004 +++ ./session.c Fri Jan 30 11:38:02 2004 @@ -66,6 +66,10 @@ #include "ssh-gss.h" #endif +#ifdef ANL_AFS_PAG +int get_afs_token(char * pgm, char ** env, char *homedir, int setpag); +#endif + /* func */ Session *session_new(void); @@ -1419,6 +1423,14 @@ */ environ = env; +#ifdef ANL_AFS_PAG + /* Get PAG and AFS token using external program and KRB5CCNAME */ + if (options.kerberos_get_afs_token) { + debug("Getting AFS token"); + get_afs_token(NULL, env, pw->pw_dir, 1); + } +#endif + #if defined(HEIMDAL) && defined(AFS) /* * At this point, we check to see if AFS is active and if we have @@ -2216,3 +2228,119 @@ if (!use_privsep || mm_is_monitor()) session_destroy_all(session_pty_cleanup2); } + +#ifdef ANL_AFS_PAG +/* gafstoken.c + + A generic routine to get an AFS token by calling + an external program. + + This routine is generic in that it does not depend on + any specific implementation of AFS, or Kerberos. + This will allow a deamon to be configured, compiled + and linked without any AFS or Kerberos dependencies + and can thus avoid conflicts between these packages. + The resulting deamon executable can be run on a system with + or without AFS. + + Examples of external programs that could be called + are aklog, afslog, gssklog, klog, ak5log or even a script + to call one of these. + + The external program is expected to support + (or ignore) the -setpag and -path <homedir> + + Parameters to gafstoken: + + char * external_program - path to the executable + this would be set by configure, or defaulted + in some way. If NULL a built in location is used. + + char **env - Environment to run under. This + should include any environment variables needed + by the external program such as KRB5CCNAME + or X509_USER_PROXY These would have been set + by GSSAPI or PAM. If NULL, the current environment + is used. + + char * homedir - A file location, if in AFS the + external program will attempt to get a token + for the cell containing it. If NULL attempt + to get a token for the default cell of the client. + + int setpag - Used to tell external program to get + an AFS PAG. The caller's process must be a process + that will be an ancestor of the user's process. + + Returns: + -1 - some system error, see errno; + 0 - the external program if present was called and + MAY have worked. + + The caller should not need to test the return code, and should + continue with or without the AFS token or PAG. + + */ + +#ifndef _PATH_AFS_EXTERNAL_PROGRAM +#define _PATH_AFS_EXTERNAL_PROGRAM "/usr/libexec/get-afs-token" +#endif + +int +get_afs_token(char * external_program, + char ** env, + char * homedir, + int setpag) +{ + pid_t pid; + int status; + struct stat stx; + char * ppath = _PATH_AFS_EXTERNAL_PROGRAM; + char * args[5]; /* arg0, -setpag, -path, homedir, NULL */ + int argi = 0; + + if (external_program) + ppath = external_program; + + /* test if external program exists */ + if (stat(ppath, &stx)) + return 0; /* does not exist, skip getting PAG and token */ + + args[argi++] = "getafstoken"; + if (setpag) + args[argi++] = "-setpag"; + if (homedir) { + args[argi++] = "-path"; + args[argi++] = homedir; + } + args[argi] = NULL; + + if ((pid = fork()) < 0) { + return -1; /* see errno */ + } + + if (pid == 0) { + /* Don't want any output confusing the deamon */ + close(1); + open("/dev/null",O_WRONLY); + close(2); + open("/dev/null",O_WRONLY); + + if (env) + execve(ppath, args, env); + else + execv(ppath, args); + exit(127); /* exec failed! Should never get here */ + } + + while (waitpid(pid, &status, 0) < 0) { + if (errno != EINTR) + break; + } + + /* we could set a return code based on status, + * be we want to go on with or without a token */ + + return 0; +} +#endif --- ./,Makefile.in Fri Nov 21 06:48:55 2003 +++ ./Makefile.in Thu Jan 29 11:22:40 2004 @@ -22,6 +22,7 @@ VPATH=@srcdir@ SSH_PROGRAM=@bindir@/ssh ASKPASS_PROGRAM=$(libexecdir)/ssh-askpass +AFS_EXTERNAL_PROGRAM=$(libexecdir)/get-afs-token SFTP_SERVER=$(libexecdir)/sftp-server SSH_KEYSIGN=$(libexecdir)/ssh-keysign RAND_HELPER=$(libexecdir)/ssh-rand-helper @@ -32,6 +33,7 @@ PATHS= -DSSHDIR=\"$(sysconfdir)\" \ -D_PATH_SSH_PROGRAM=\"$(SSH_PROGRAM)\" \ -D_PATH_SSH_ASKPASS_DEFAULT=\"$(ASKPASS_PROGRAM)\" \ + -D_PATH_AFS_EXTERNAL_PROGRAM=\"$(AFS_EXTERNAL_PROGRAM)\" \ -D_PATH_SFTP_SERVER=\"$(SFTP_SERVER)\" \ -D_PATH_SSH_KEY_SIGN=\"$(SSH_KEYSIGN)\" \ -D_PATH_SSH_PIDDIR=\"$(piddir)\" \ "Douglas E. Engert" wrote:> > Rather then implementing kafs in MIT Kerberos, I would like to > suggest an alternative which has advantages to all parties. > > The OpenSSH sshd needs to do two things: > (1) sets a PAG in the kernel, > (2) obtains an AFS token storing it in the kernel. > > It can use the Kerberos credentials either obtained via GSSAPI > delegation, PAM or other kerberos login code in the sshd. > > The above two actions can be accomplished by a separate process, > which can be forked and execd by the sshd and passed the environment > which may have a KREB5CCNAME pointing at the Kerberos ticket cache > Other parameters such as the home directory could also be passed. > > This would then allow simple code in OpenSSH that does not depend > on OpenAFS, Hiemdal or MIT code to fork/exec the process that does > all the work. This would be called by the process that would > eventially become the user's shell process and is run as the user. > > OpenSSH could be built on systems that may or may not have AFS > installed and run on a system with or without AFS. The decision > is based on the existence of the executable and any options > in sshd_config. > > In its simplest form, all that is needed is: > > system("/usr/ssh/libexec/aklog -setpag") > > This is a little over simplified as there should be a test if the > executable exists, processing of some return codes, making sure the > environment is set, setting some time limit. etc. But the point is > there is no compile dependence on OpenAFS, MIT or Hiemdal by the > OpenSSH sshd, and any failure of the process will not effect the sshd. > > We have been using something like this for years which issues a > syscall to set a PAG for the current process, then fork/exec ak5log. > Our current mode to OpenSSH in session.c is as simple as: > > krb5_afs_pag_env(NULL, env); > > It is currently built with the MIT Kerberos code for historic reasons, > but could be seperate as it has no real dependency on the MIT code. > > I would hope that the members of the OpenSSH community who use OpenAFS, > Hiemdal and/or MIT could agree on a simple command line interface that > would encourage the builders of OpenSSH to always have this enabled. > > -- > > Douglas E. Engert <DEEngert at anl.gov> > Argonne National Laboratory > 9700 South Cass Avenue > Argonne, Illinois 60439 > (630) 252-5444-- Douglas E. Engert <DEEngert at anl.gov> Argonne National Laboratory 9700 South Cass Avenue Argonne, Illinois 60439 (630) 252-5444