/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

/*
 * First know revision of this was published internally at Sun
 * in 1997.
 */

/*
 * pam_root_console.c - disallows root login on console if CONSOLE=
 *			defined in /etc/default/login
 *
 * Compile:
 *
 *	cc pam_root_console.c -o pam_root_console.so.1 -Kpic -G -lcmd
 *
 * Install:
 *
 *	cp pam_root_console.so.1 /usr/lib/security
 *	chmod 644 /usr/lib/security/pam_root_console.so.1
 *	ln -s pam_root_console.so.1 /usr/lib/security/pam_root_console.so
 *
 *      Add the following lines to /etc/pam.conf:
 *	other	auth required	/usr/lib/security/pam_unix.so.1
 *	other	auth required	/usr/lib/security/pam_root_console.so.1
 *
 *	su	auth required	/usr/lib/security/pam_unix.so.1
 *
 *
 */
#include <stdio.h>
#include <pwd.h>
#include <string.h>
#include <deflt.h>
#include <security/pam_appl.h>

#define LOGINDEFLT	DEFLT "/login"

char NO_LOGIN_MESSAGE[] = { "Login incorrect" };

/*
 * pam_sm_authenticate - Access allowed ?
 */
 
int
pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
{
	char *username = NULL;
	char pwd_buf[1024];
	struct passwd pwd;
	struct group grp;
	char *ttyn = NULL;
	char *defp = NULL;
	char *Console = NULL;
	struct pam_conv *conversation;
	struct pam_message message;
	struct pam_message *pmessage = &message;
	struct pam_response *resp = NULL;

	if (pam_get_item(pamh, PAM_USER, (void**)&username) != PAM_SUCCESS) {
		return (PAM_SERVICE_ERR);
	}

	if (getpwnam_r(username, &pwd, pwd_buf, sizeof(pwd_buf)) == NULL) {
		return (PAM_USER_UNKNOWN);
	}

	if (pwd.pw_uid != 0) {
		return (PAM_SUCCESS);
	}

	if (pam_get_item(pamh, PAM_TTY, (void**)&ttyn) != PAM_SUCCESS) {
		return PAM_SERVICE_ERR;
	}

	if (defopen(LOGINDEFLT) != 0) {
		return PAM_SERVICE_ERR;
	}

	if ((defp = defread("CONSOLE=")) != NULL) {
		Console = strdup(defp);
	}

	(void) defopen((char*)NULL);

	if ((Console != NULL) && (strcmp(ttyn, Console) != 0)) {
		audit_login_not_console();

		message.msg_style = PAM_ERROR_MSG;

		message.msg = NO_LOGIN_MESSAGE;

		pam_get_item (pamh, PAM_CONV, (void**)&conversation);
		conversation->conv(1, (struct pam_message**)&pmessage,
		    &resp, conversation->appdata_ptr);

		return (PAM_AUTH_ERR);
	} else {
		/* 
		 * CONSOLE= doesn't exit in /etc/default/login so
		 * no restriction
		 */
		return (PAM_SUCCESS);
	}
}

/* This module doesn't set credentials */
pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv)
{
        return (PAM_IGNORE);
}
