/* pam_apparmor module */ /* * $Id$ * * Written by Jesse Michael 2006/08/24 * * Based off of pam_motd by: * Ben Collins 2005/10/04 * Michael K. Johnson 1996/10/24 * */ #include #include #include #include #include #include #include #include #include #include #include /* * here, we make a definition for the externally accessible function * in this file (this definition is required for static a module * but strongly encouraged generally) it is used to instruct the * modules include file to define the function prototypes. */ #define PAM_SM_SESSION #include #define DEBUG 0 /* --- session management functions (only) --- */ PAM_EXTERN int pam_sm_close_session (pam_handle_t *pamh, int flags, int argc, const char **argv) { return PAM_IGNORE; } PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv) { int fd, retval, pam_retval = PAM_SUCCESS; unsigned int magic_token; const char *user; struct passwd *pw; struct group *gr; /* grab the target user name */ retval = pam_get_user(pamh, &user, NULL); if (retval != PAM_SUCCESS || user == NULL || *user == '\0') { pam_syslog(pamh, LOG_ERR, "Can't determine user\n"); return PAM_USER_UNKNOWN; } pw = getpwnam(user); if(!pw) { pam_syslog(pamh, LOG_ERR, "Can't determine group for user %s\n", user); return PAM_PERM_DENIED; } gr = getgrgid(pw->pw_gid); if(!gr || !gr->gr_name) { pam_syslog(pamh, LOG_ERR, "Can't read info for group %d\n", pw->pw_gid); return PAM_PERM_DENIED; } fd = open("/dev/urandom", O_RDONLY); if (fd < 0) { pam_syslog(pamh, LOG_ERR, "Can't open /dev/urandom\n"); return PAM_PERM_DENIED; } /* * the magic token needs to be non-zero otherwise, we won't be able * to probe for hats */ do { retval = read(fd, (void *) &magic_token, sizeof(magic_token)); if (retval < 0) { pam_syslog(pamh, LOG_ERR, "Can't read from /dev/urandom\n"); return PAM_PERM_DENIED; } } while ((magic_token == 0) || (retval != sizeof(magic_token))); close(fd); /* change into the group hat */ retval = change_hat(gr->gr_name, magic_token); if (retval < 0) { /* failed to change into group hat, so we'll jump back out */ retval = change_hat(NULL, magic_token); if (retval == 0) { /* and try to change to the DEFAULT hat instead */ retval = change_hat("DEFAULT", magic_token); if (retval < 0) { /* * failed to change into default hat, so * we'll jump back out */ retval = change_hat(NULL, magic_token); pam_syslog(pamh, LOG_ERR, "Can't change to DEFAULT hat\n"); pam_retval = PAM_PERM_DENIED; } else { #if DEBUG pam_syslog(pamh, LOG_DEBUG, "Successfully changed to DEFAULT hat\n"); #endif } } else { /* * changing into the group hat and attempting to * jump back out both failed. that most likely * means that either apparmor is not loaded or we * don't have a profile loaded for this application. * in this case, we want to allow the pam operation * to succeed. */ } } else { #if DEBUG pam_syslog(pamh, LOG_DEBUG, "Successfully changed to %s hat\n", gr->gr_name); #endif } /* * zero out the magic token so an attacker wouldn't be able to * just grab it out of process memory and instead would need to * brute force it */ memset(&magic_token, 0, sizeof(magic_token)); return pam_retval; } #ifdef PAM_STATIC /* static module data */ struct pam_module _pam_apparmor_modstruct = { "pam_apparmor", NULL, NULL, NULL, pam_sm_open_session, pam_sm_close_session, NULL, }; #endif /* end of module definition */