pam_nologin.c revision 1.4
11.4Sthorpej/*	$NetBSD: pam_nologin.c,v 1.4 2005/03/31 15:11:54 thorpej Exp $	*/
21.2Schristos
31.1Schristos/*-
41.1Schristos * Copyright 2001 Mark R V Murray
51.1Schristos * All rights reserved.
61.1Schristos * Copyright (c) 2001 Networks Associates Technology, Inc.
71.1Schristos * All rights reserved.
81.1Schristos *
91.1Schristos * Portions of this software were developed for the FreeBSD Project by
101.1Schristos * ThinkSec AS and NAI Labs, the Security Research Division of Network
111.1Schristos * Associates, Inc.  under DARPA/SPAWAR contract N66001-01-C-8035
121.1Schristos * ("CBOSS"), as part of the DARPA CHATS research program.
131.1Schristos *
141.1Schristos * Redistribution and use in source and binary forms, with or without
151.1Schristos * modification, are permitted provided that the following conditions
161.1Schristos * are met:
171.1Schristos * 1. Redistributions of source code must retain the above copyright
181.1Schristos *    notice, this list of conditions and the following disclaimer.
191.1Schristos * 2. Redistributions in binary form must reproduce the above copyright
201.1Schristos *    notice, this list of conditions and the following disclaimer in the
211.1Schristos *    documentation and/or other materials provided with the distribution.
221.1Schristos * 3. The name of the author may not be used to endorse or promote
231.1Schristos *    products derived from this software without specific prior written
241.1Schristos *    permission.
251.1Schristos *
261.1Schristos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
271.1Schristos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
281.1Schristos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
291.1Schristos * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
301.1Schristos * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
311.1Schristos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
321.1Schristos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
331.1Schristos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
341.1Schristos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
351.1Schristos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
361.1Schristos * SUCH DAMAGE.
371.1Schristos */
381.1Schristos
391.1Schristos#include <sys/cdefs.h>
401.2Schristos#ifdef __FreeBSD__
411.1Schristos__FBSDID("$FreeBSD: src/lib/libpam/modules/pam_nologin/pam_nologin.c,v 1.10 2002/04/12 22:27:21 des Exp $");
421.2Schristos#else
431.4Sthorpej__RCSID("$NetBSD: pam_nologin.c,v 1.4 2005/03/31 15:11:54 thorpej Exp $");
441.2Schristos#endif
451.2Schristos
461.1Schristos
471.1Schristos#include <sys/types.h>
481.1Schristos#include <sys/stat.h>
491.1Schristos#include <fcntl.h>
501.1Schristos#include <login_cap.h>
511.1Schristos#include <pwd.h>
521.3Smanu#include <errno.h>
531.3Smanu#include <string.h>
541.1Schristos#include <stdio.h>
551.1Schristos#include <stdlib.h>
561.1Schristos#include <unistd.h>
571.1Schristos
581.1Schristos#define PAM_SM_AUTH
591.1Schristos
601.1Schristos#include <security/pam_appl.h>
611.1Schristos#include <security/pam_modules.h>
621.1Schristos#include <security/pam_mod_misc.h>
631.1Schristos
641.3Smanu#define	NOLOGIN	"/etc/nologin"
651.1Schristos
661.1Schristosstatic char nologin_def[] = NOLOGIN;
671.1Schristos
681.1SchristosPAM_EXTERN int
691.1Schristospam_sm_authenticate(pam_handle_t *pamh, int flags __unused,
701.1Schristos    int argc __unused, const char *argv[] __unused)
711.1Schristos{
721.1Schristos	login_cap_t *lc;
731.4Sthorpej	struct passwd *pwd, pwres;
741.1Schristos	struct stat st;
751.1Schristos	int retval, fd;
761.3Smanu	int ignorenologin = 0;
771.3Smanu	int rootlogin = 0;
781.1Schristos	const char *user, *nologin;
791.1Schristos	char *mtmp;
801.4Sthorpej	char pwbuf[1024];
811.1Schristos
821.3Smanu	if ((retval = pam_get_user(pamh, &user, NULL)) != PAM_SUCCESS)
831.3Smanu		return retval;
841.1Schristos
851.1Schristos	PAM_LOG("Got user: %s", user);
861.1Schristos
871.3Smanu	/*
881.3Smanu	 * For root, the default is to ignore nologin, but the
891.3Smanu	 * ignorenologin capability can override this, so we
901.3Smanu	 * set the default appropriately.
911.3Smanu	 *
921.3Smanu	 * Do not allow login of unexisting users, so that a directory
931.3Smanu	 * failure will not cause the nologin capability to be ignored.
941.3Smanu	 */
951.4Sthorpej	if (getpwnam_r(user, &pwres, pwbuf, sizeof(pwbuf), &pwd) != 0) {
961.3Smanu		return PAM_USER_UNKNOWN;
971.3Smanu	} else {
981.3Smanu		if (pwd->pw_uid == 0)
991.3Smanu			rootlogin = 1;
1001.3Smanu	}
1011.3Smanu
1021.1Schristos	lc = login_getclass(NULL);
1031.3Smanu	ignorenologin = login_getcapbool(lc, "ignorenologin", rootlogin);
1041.1Schristos	nologin = login_getcapstr(lc, "nologin", nologin_def, nologin_def);
1051.1Schristos	login_close(lc);
1061.1Schristos	lc = NULL;
1071.1Schristos
1081.3Smanu	if (ignorenologin)
1091.3Smanu		return PAM_SUCCESS;
1101.3Smanu
1111.3Smanu	if ((fd = open(nologin, O_RDONLY, 0)) == -1) {
1121.3Smanu		/*
1131.3Smanu		 * The file does not exist, login is granted
1141.3Smanu		 */
1151.3Smanu		if (errno == ENOENT)
1161.3Smanu			return PAM_SUCCESS;
1171.3Smanu
1181.3Smanu		/*
1191.3Smanu		 * open failed, but the file exists. This could be
1201.3Smanu		 * a temporary problem (system resources exausted):
1211.3Smanu		 * Refuse the login.
1221.3Smanu		 */
1231.3Smanu		PAM_LOG("Cannot open %s file: %s", nologin, strerror(errno));
1241.3Smanu		return PAM_AUTH_ERR;
1251.1Schristos	}
1261.1Schristos
1271.3Smanu	PAM_LOG("Opened %s file", nologin);
1281.3Smanu
1291.1Schristos	if (fstat(fd, &st) < 0)
1301.3Smanu		return PAM_AUTH_ERR;
1311.1Schristos
1321.1Schristos	mtmp = malloc(st.st_size + 1);
1331.1Schristos	if (mtmp != NULL) {
1341.1Schristos		read(fd, mtmp, st.st_size);
1351.1Schristos		mtmp[st.st_size] = '\0';
1361.1Schristos		pam_error(pamh, "%s", mtmp, NULL);
1371.1Schristos		free(mtmp);
1381.1Schristos	}
1391.1Schristos
1401.3Smanu	PAM_VERBOSE_ERROR("Administrator refusing you: %s", nologin);
1411.1Schristos
1421.3Smanu	return PAM_AUTH_ERR;
1431.1Schristos}
1441.1Schristos
1451.1SchristosPAM_EXTERN int
1461.1Schristospam_sm_setcred(pam_handle_t *pamh __unused, int flags __unused,
1471.1Schristos    int argc __unused, const char *argv[] __unused)
1481.1Schristos{
1491.1Schristos
1501.1Schristos	return (PAM_SUCCESS);
1511.1Schristos}
1521.1Schristos
1531.1SchristosPAM_MODULE_ENTRY("pam_nologin");
154