Russ Allbery wrote:
Arne Nordmark <[EMAIL PROTECTED]> writes:

Package: openafs-modules-source
Version: 1.4.2-2
Severity: normal

aklog -setpag no longer works with the kernel module from 1.4.2-2.  This
breaks libpam-openafs-session, so users no longer get token upon login.

Unfortunately, this was an intentional upstream change and it may not be
possible to restore this behavior safely.  Apparently the intrusive
manipulation of the Linux kernel required to add one's parent process to a
new group is nasty enough that it was causing race conditions and was
becoming hard to maintain.  It's also a disgusting hack that the kernel
developers are never going to want to support.

Writing a new AFS PAM module that doesn't require this hack is at the top
of my priority list, and I will do what I can to get a fix for this into
etch, probably by teaching libpam-openafs-session how to create the PAG
itself directly.  This is hard to do in general, but on Linux with a
current OpenAFS client the interface via /proc/fs/openafs/afs_ioctl is
simple enough that we may be able to use it directly as a workaround until
we have a more general solution.


Thank you very much for this encouraging information. Funny though that a change like this happens between (-fc4) and (final).

For what it is worth, I recompiled (for etch) the port I had done of libpam-openafs-session to Heimdal for (probably) woody (where krb5 and heimdal conflicted more than they do now). This code (Heimdal afslog does not have a switch corresponding to -setpag, so I added a call to k_setpag() before running afslog) seems to work and put the tokens in a new PAG. I am attaching that file for your reference.

Thanks again,
Arne

/*
 * pam_krb5_sess.c
 *
 * PAM session management functions for pam_openafs_session
 * 
 *
 */
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <syslog.h>
#include <pwd.h>
#include <stdio.h>
#include <krb5.h>
#include <kafs.h>

#define KERBCACHE "KRB5CCNAME"
#define AFSLOG "/usr/bin/afslog"

#define MAXBUF 256

/* A useful logging macro */
/* from libpam-krb5 */
#define DLOG(error_func, error_msg) \
if (debug) \
    syslog(LOG_DEBUG, "pam_openafs_session: %s: %s", \
	   error_func, error_msg)
#define ELOG(error_func, error_msg) \
    syslog(LOG_ERR, "pam_openafs_session: %s: %s", \
	   error_func, error_msg)


#include <security/pam_appl.h>
#include <security/pam_modules.h>

/* We need to store whether afslog has been run.
   We do this with the afslog_run data item.  The value doesn't matter, so we use an int.*/
static int dummy;

static void dummy_cleanup (pam_handle_t *pamh, void * data, int end_status)
{
  return;
}


/* Initiate session management */
int
pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv)
{
  pid_t pid;
  int debug = 0;
  int newpag = 1;
  int status;
  int i;
  const char *name;
  struct passwd *pw;
  char *envi[2];
  char namecache[]={KERBCACHE};
  const char *filecache;
  char buf[MAXBUF];    
  int pamret;
  const void *test_data;
  envi[1]=NULL;
  
  for (i = 0; i < argc; i++) {
    if (strcmp(argv[i], "debug") == 0)
      debug = 1;
    if (strcmp(argv[i], "no_newpag") == 0)
      newpag = 0;
  }

  if ( pam_get_data (pamh, "afslog_run", &test_data) == 0) {
    DLOG ("pM_open_session", "afslog already run");
    return PAM_SUCCESS;
  }
      
  if(pam_get_user(pamh, &name, "") != PAM_SUCCESS )
    return PAM_SERVICE_ERR;
  pw =getpwnam (name);
  if(!pw) {
    ELOG("getpwnam","Unable to get the user UID");
    return PAM_SERVICE_ERR;
  }
  filecache=pam_getenv(pamh,namecache);    
  if (!filecache) {
    DLOG ("open_session", "Could not find Kerberos tickets; not running afslog");
    return PAM_SUCCESS;
  }
  if ((pamret = pam_set_data (pamh, "afslog_run", (void *) &dummy, dummy_cleanup))
      != 0 ) {
    ELOG ("open_session", "Unable to set PAM data");
    return pamret;
  }
  
  if (newpag)
    if (k_hasafs()) {
      k_setpag();
      DLOG("open_session","setpag");
    }

  DLOG("open_session","fork..");
  
  pid=fork();  
  if(pid==0) { /* il figlio */ 
    
    if(setuid(pw->pw_uid) < 0) {
      ELOG("setuid","Unable to set the appropriate UID");
      exit(1);
    }
    
    snprintf(buf,MAXBUF-1,"%s=%s",namecache,filecache);
    envi[0]=buf;
    DLOG("ENVIRONNEMENT", envi[0]);
    
    execle( AFSLOG,"afslog", NULL,envi);
    
    ELOG("open_session","fatal error");
    exit(-1);
  }
  waitpid(pid, &status, 0);
  if(WIFEXITED(status)) {
    DLOG("KRB5 OPENSESSION", "OK !");
    return PAM_SUCCESS;
  }
  return PAM_SESSION_ERR;
}


/* Terminate session management */
int
pam_sm_close_session(pam_handle_t *pamh, 
		     int flags, int argc, const char **argv)
{
  const char *name;
  struct passwd *pw;
  char *envi[2];
  char namecache[]={KERBCACHE};
  const char *filecache;
  char buf[MAXBUF];    
  int i,debug=0;
  int UID=-1;
  pid_t pid;
  int status;
  const void *data;

  
  envi[1]=NULL;
  for (i = 0; i < argc; i++) {
    if (strcmp(argv[i], "debug") == 0) {
      debug = 1;
      break;
    }
  }
  
  if (!pam_get_data (pamh, "afslog_run", &data) ) {
    DLOG ("pam_close_session", "Afslog never run so not running unlog");
      return PAM_SUCCESS;
  }
  
  /* ???? */
  if(pam_get_user(pamh, &name, "") != PAM_SUCCESS )
    exit(-1);
  
  
  pw=getpwnam (name);
  if(!pw) {
    ELOG("getpwnam","Unable to get the user UID");
    exit(-1);
  }
  
  UID=pw->pw_uid;
  if(setuid(UID) < 0) {
    ELOG("setuid","Unable to set the appropriate UID");
    exit(-1);
  }
  
  filecache=pam_getenv(pamh,namecache);    
  snprintf(buf,MAXBUF-1,"%s=%s",namecache,filecache);
  envi[0]=buf;
  DLOG("ENVIRONNEMENT", envi[0]);
  
  DLOG("close_session","fork..1");  
  
  pid=fork();      
  if(pid==0) { /* il figlio */ 
    execle( AFSLOG,"afslog","-u",NULL,envi);    
    ELOG("close_session","execle fatal error");
    exit(-1);
  }
  waitpid(pid, &status, 0);
  if(!WIFEXITED(status)) {
    ELOG("KRB5 CLOSESSION", "ERROR In fork 1!");
    return PAM_SESSION_ERR;
  }
  
  return PAM_SUCCESS;
}


int
pam_sm_setcred(pam_handle_t *pamh, int flags, int argc,
	       const char **argv)
{
  if (flags == PAM_ESTABLISH_CRED)
    return pam_sm_open_session (pamh, flags, argc, argv);
return PAM_SUCCESS;
}

int
pam_sm_authenticate (pam_handle_t *pamh, int flags, int argc, const char **argv) {
  return PAM_SUCCESS;
}

Reply via email to