Use the current user's login class for the decisions about where
  the nologin(5) file is located and whether the user may bypass its
  restriction.

  Add some error checks.

  Revision  Changes    Path
  1.7       +16 -15    src/lib/libpam/modules/pam_nologin/pam_nologin.8
  1.13      +42 -29    src/lib/libpam/modules/pam_nologin/pam_nologin.c

Note: To avoid POLA violation, the merged module still lets root
in irrespective of login.conf settings.  In HEAD, root has to have
an explicit "ignorenologin" capability to bypass nologin(5).

PR:	bin/107612
This commit is contained in:
yar 2007-07-12 14:11:57 +00:00
parent f510b9f527
commit fa260264c0
2 changed files with 65 additions and 45 deletions

View File

@ -50,23 +50,24 @@ It also provides a null function for session management.
.Ss NoLogin Authentication Module
The NoLogin authentication component
.Pq Fn pam_sm_authenticate ,
always returns success for the superuser,
and returns success for all other users
if the file
.Pa /var/run/nologin
does not exist.
If
.Pa /var/run/nologin
does exist,
then its contents are echoed
to non-superusers
verifies whether logins are administratively disabled via
.Xr nologin 5 .
It returns success if the user's login class has an "ignorenologin"
capability specified in
.Xr login.conf 5
or the
.Xr nologin 5
file does not exist.
If neither condition is met,
then the contents of
.Xr nologin 5
are echoed
before failure is returned.
If a "nologin" capability
is specified in
The location of
.Xr nologin 5
is specified by a "nologin" capability in
.Xr login.conf 5 ,
then the file thus specified
is used instead.
This usually defaults to
which defaults to
.Pa /var/run/nologin .
.Pp
The following options may be passed to the authentication module:

View File

@ -52,9 +52,9 @@ __FBSDID("$FreeBSD$");
#include <security/pam_modules.h>
#include <security/pam_mod_misc.h>
#define NOLOGIN "/var/run/nologin"
#define _PATH_NOLOGIN "/var/run/nologin"
static char nologin_def[] = NOLOGIN;
static char nologin_def[] = _PATH_NOLOGIN;
PAM_EXTERN int
pam_sm_authenticate(pam_handle_t *pamh, int flags __unused,
@ -64,6 +64,7 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags __unused,
struct passwd *pwd;
struct stat st;
int retval, fd;
ssize_t ss;
const char *user, *nologin;
char *mtmp;
@ -73,42 +74,60 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags __unused,
PAM_LOG("Got user: %s", user);
lc = login_getclass(NULL);
nologin = login_getcapstr(lc, "nologin", nologin_def, nologin_def);
login_close(lc);
lc = NULL;
pwd = getpwnam(user);
if (pwd == NULL)
return (PAM_USER_UNKNOWN);
fd = open(nologin, O_RDONLY, 0);
if (fd < 0)
/*
* Old bug compatibility in RELENG_6: always let root in.
*/
if (pwd->pw_uid == 0)
return (PAM_SUCCESS);
PAM_LOG("Opened %s file", NOLOGIN);
pwd = getpwnam(user);
if (pwd && pwd->pw_uid == 0)
retval = PAM_SUCCESS;
else {
if (!pwd)
retval = PAM_USER_UNKNOWN;
else
retval = PAM_AUTH_ERR;
/*
* login_getpwclass(3) will select the "root" class by default
* if pwd->pw_uid is 0. That class should have "ignorenologin"
* capability so that super-user can bypass nologin.
*/
lc = login_getpwclass(pwd);
if (lc == NULL) {
PAM_LOG("Unable to get login class for user %s", user);
return (PAM_SERVICE_ERR);
}
if (fstat(fd, &st) < 0)
return (retval);
mtmp = malloc(st.st_size + 1);
if (mtmp != NULL) {
read(fd, mtmp, st.st_size);
mtmp[st.st_size] = '\0';
pam_error(pamh, "%s", mtmp, NULL);
free(mtmp);
if (login_getcapbool(lc, "ignorenologin", 0)) {
login_close(lc);
return (PAM_SUCCESS);
}
if (retval != PAM_SUCCESS)
PAM_VERBOSE_ERROR("Administrator refusing you: %s", NOLOGIN);
nologin = login_getcapstr(lc, "nologin", nologin_def, nologin_def);
return (retval);
fd = open(nologin, O_RDONLY, 0);
if (fd < 0) {
login_close(lc);
return (PAM_SUCCESS);
}
PAM_LOG("Opened %s file", nologin);
if (fstat(fd, &st) == 0) {
mtmp = malloc(st.st_size + 1);
if (mtmp != NULL) {
ss = read(fd, mtmp, st.st_size);
if (ss > 0) {
mtmp[ss] = '\0';
pam_error(pamh, "%s", mtmp);
}
free(mtmp);
}
}
PAM_VERBOSE_ERROR("Administrator refusing you: %s", nologin);
close(fd);
login_close(lc);
return (PAM_AUTH_ERR);
}
PAM_EXTERN int