/* * pam_krb5_sess.c * * PAM session management functions for pam_openafs-krb5 * * */ #include #include #include #include #include #include #include #include #define KERBCACHE "KRB5CCNAME" #define AKLOG "/usr/bin/aklog" #define UNLOG "/usr/bin/unlog" #define MAXBUF 256 /* A useful logging macro */ /* from libpam-krb5 */ #define DLOG(error_func, error_msg) \ if (debug) \ syslog(LOG_DEBUG, "pam_openafs-krb5: %s: %s", \ error_func, error_msg) #define ELOG(error_func, error_msg) \ syslog(LOG_ERR, "pam_openafs-krb5: %s: %s", \ error_func, error_msg) #include #include /* We need to store whether aklog has been run. We do this with the aklog_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 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; break; } } if ( pam_get_data (pamh, "aklog_run", &test_data) == 0) { DLOG ("pM_open_session", "aklog 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 aklog"); return PAM_SUCCESS; } if ((pamret = pam_set_data (pamh, "aklog_run", (void *) &dummy, dummy_cleanup)) != 0 ) { ELOG ("open_session", "Unable to set PAM data"); return pamret; } 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( AKLOG,"aklog","-setpag", 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, "aklog_run", &data) ) { DLOG ("pam_close_session", "Aklog 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( UNLOG,"unlog",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; } /* user has re-authenticated themselves (i.e. unlocked a screensaver) */ int pam_sm_authenticate (pam_handle_t *pamh, int flags, int argc, const char **argv) { pid_t pid; int debug = 0; 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; break; } } if ( pam_get_data (pamh, "aklog_run", &test_data) == 0) { DLOG ("pM_authenticate", "aklog already run, running again"); } else { DLOG ("pM_authenticate", "aklog not run, running"); } 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 ("authenticate", "Could not find Kerberos tickets; not running aklog"); return PAM_SUCCESS; } if ((pamret = pam_set_data (pamh, "aklog_run", (void *) &dummy, dummy_cleanup)) != 0 ) { ELOG ("authenticate", "Unable to set PAM data"); return pamret; } DLOG("authenticate","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( AKLOG,"aklog","-setpag", NULL,envi); ELOG("authenticate","fatal error"); exit(-1); } waitpid(pid, &status, 0); if(WIFEXITED(status)) { DLOG("KRB5 OPENSESSION", "OK !"); return PAM_SUCCESS; } return PAM_SESSION_ERR; }