189728Sdes/*- 289728Sdes * Copyright (c) 1980, 1987, 1988, 1991, 1993, 1994 389728Sdes * The Regents of the University of California. All rights reserved. 489728Sdes * Copyright (c) 2001 Mark R V Murray 589728Sdes * All rights reserved. 692297Sdes * Copyright (c) 2001 Networks Associates Technology, Inc. 789728Sdes * All rights reserved. 8125046Sdes * Copyright (c) 2004 Joe R. Doupnik 9125046Sdes * All rights reserved. 1089728Sdes * 1189728Sdes * Portions of this software were developed for the FreeBSD Project by 1289728Sdes * ThinkSec AS and NAI Labs, the Security Research Division of Network 1389728Sdes * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 1489728Sdes * ("CBOSS"), as part of the DARPA CHATS research program. 1589728Sdes * 1689728Sdes * Redistribution and use in source and binary forms, with or without 1789728Sdes * modification, are permitted provided that the following conditions 1889728Sdes * are met: 1989728Sdes * 1. Redistributions of source code must retain the above copyright 2089728Sdes * notice, this list of conditions and the following disclaimer. 2189728Sdes * 2. Redistributions in binary form must reproduce the above copyright 2289728Sdes * notice, this list of conditions and the following disclaimer in the 2389728Sdes * documentation and/or other materials provided with the distribution. 2489728Sdes * 3. The name of the author may not be used to endorse or promote 2589728Sdes * products derived from this software without specific prior written 2689728Sdes * permission. 2789728Sdes * 4. Neither the name of the University nor the names of its contributors 2889728Sdes * may be used to endorse or promote products derived from this software 2989728Sdes * without specific prior written permission. 3089728Sdes * 3189728Sdes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 3289728Sdes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3389728Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 3489728Sdes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 3589728Sdes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3689728Sdes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3789728Sdes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3889728Sdes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3989728Sdes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 4089728Sdes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 4189728Sdes * SUCH DAMAGE. 4289728Sdes */ 4389728Sdes 4489728Sdes#include <sys/cdefs.h> 4589728Sdes__FBSDID("$FreeBSD$"); 4689728Sdes 4789728Sdes#define _BSD_SOURCE 4889728Sdes 49202566Sed#include <sys/time.h> 50227314Sed 51227314Sed#include <paths.h> 52202566Sed#include <stdlib.h> 53202566Sed#include <string.h> 5489728Sdes#include <time.h> 55202566Sed#include <unistd.h> 56202211Sed#include <utmpx.h> 5789728Sdes 5889728Sdes#define PAM_SM_SESSION 5989728Sdes 6090229Sdes#include <security/pam_appl.h> 6189728Sdes#include <security/pam_modules.h> 6290229Sdes#include <security/pam_mod_misc.h> 6389728Sdes 64202566Sed#define PAM_UTMPX_ID "utmpx_id" 65202566Sed 6689728SdesPAM_EXTERN int 6794564Sdespam_sm_open_session(pam_handle_t *pamh, int flags, 6894564Sdes int argc __unused, const char *argv[] __unused) 6989728Sdes{ 70202566Sed struct utmpx *utx, utl; 71106966Speter time_t t; 72123448Sdes const char *user; 73123448Sdes const void *rhost, *tty; 74202566Sed char *id; 75200413Sed int pam_err; 7689728Sdes 7794564Sdes pam_err = pam_get_user(pamh, &user, NULL); 7889728Sdes if (pam_err != PAM_SUCCESS) 7994564Sdes return (pam_err); 80269115Sdes if (user == NULL) 8194564Sdes return (PAM_SERVICE_ERR); 8289728Sdes PAM_LOG("Got user: %s", user); 8389728Sdes 84123448Sdes pam_err = pam_get_item(pamh, PAM_RHOST, &rhost); 85161209Sdes if (pam_err != PAM_SUCCESS) { 86161209Sdes PAM_LOG("No PAM_RHOST"); 8797148Sdes goto err; 88161209Sdes } 89123448Sdes pam_err = pam_get_item(pamh, PAM_TTY, &tty); 90161209Sdes if (pam_err != PAM_SUCCESS) { 91161209Sdes PAM_LOG("No PAM_TTY"); 9297148Sdes goto err; 93161209Sdes } 9497625Sdes if (tty == NULL) { 95161209Sdes PAM_LOG("No PAM_TTY"); 9697625Sdes pam_err = PAM_SERVICE_ERR; 9797625Sdes goto err; 9897625Sdes } 99227314Sed /* Strip /dev/ component. */ 100227314Sed if (strncmp(tty, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0) 101227314Sed tty = (const char *)tty + sizeof(_PATH_DEV) - 1; 10294564Sdes 10389728Sdes if ((flags & PAM_SILENT) == 0) { 104202211Sed if (setutxdb(UTXDB_LASTLOGIN, NULL) != 0) { 105202211Sed PAM_LOG("Failed to open lastlogin database"); 106200413Sed } else { 107202211Sed utx = getutxuser(user); 108200413Sed if (utx != NULL && utx->ut_type == USER_PROCESS) { 109200413Sed t = utx->ut_tv.tv_sec; 110200413Sed if (*utx->ut_host != '\0') 111200413Sed pam_info(pamh, "Last login: %.*s from %s", 112200413Sed 24 - 5, ctime(&t), utx->ut_host); 113200413Sed else 114200413Sed pam_info(pamh, "Last login: %.*s on %s", 115200413Sed 24 - 5, ctime(&t), utx->ut_line); 116200413Sed } 117202211Sed endutxent(); 11889728Sdes } 11989728Sdes } 12094564Sdes 121202566Sed id = malloc(sizeof utl.ut_id); 122202566Sed if (id == NULL) { 123202566Sed pam_err = PAM_SERVICE_ERR; 124202566Sed goto err; 125202566Sed } 126202566Sed arc4random_buf(id, sizeof utl.ut_id); 12794564Sdes 128202566Sed pam_err = pam_set_data(pamh, PAM_UTMPX_ID, id, openpam_free_data); 129202566Sed if (pam_err != PAM_SUCCESS) { 130202566Sed free(id); 131202566Sed goto err; 132202566Sed } 133202566Sed 134202566Sed memset(&utl, 0, sizeof utl); 135202566Sed utl.ut_type = USER_PROCESS; 136202566Sed memcpy(utl.ut_id, id, sizeof utl.ut_id); 137202566Sed strncpy(utl.ut_user, user, sizeof utl.ut_user); 138202566Sed strncpy(utl.ut_line, tty, sizeof utl.ut_line); 139202566Sed if (rhost != NULL) 140202566Sed strncpy(utl.ut_host, rhost, sizeof utl.ut_host); 141202566Sed utl.ut_pid = getpid(); 142202566Sed gettimeofday(&utl.ut_tv, NULL); 143202566Sed pututxline(&utl); 144202566Sed 14596192Sdes return (PAM_SUCCESS); 14694564Sdes 14797148Sdeserr: 14896192Sdes if (openpam_get_option(pamh, "no_fail")) 14996192Sdes return (PAM_SUCCESS); 15097148Sdes return (pam_err); 15189728Sdes} 15289728Sdes 15389728SdesPAM_EXTERN int 154200413Sedpam_sm_close_session(pam_handle_t *pamh, int flags __unused, 15594564Sdes int argc __unused, const char *argv[] __unused) 15689728Sdes{ 157202566Sed struct utmpx utl; 158202566Sed const void *id; 159171544Sdes int pam_err; 16089728Sdes 161202566Sed pam_err = pam_get_data(pamh, PAM_UTMPX_ID, (const void **)&id); 162171544Sdes if (pam_err != PAM_SUCCESS) 163171544Sdes goto err; 164202566Sed 165202566Sed memset(&utl, 0, sizeof utl); 166202566Sed utl.ut_type = DEAD_PROCESS; 167202566Sed memcpy(utl.ut_id, id, sizeof utl.ut_id); 168202566Sed utl.ut_pid = getpid(); 169202566Sed gettimeofday(&utl.ut_tv, NULL); 170202566Sed pututxline(&utl); 171202566Sed 172171543Sdes return (PAM_SUCCESS); 173171544Sdes 174171544Sdes err: 175171544Sdes if (openpam_get_option(pamh, "no_fail")) 176171544Sdes return (PAM_SUCCESS); 177171544Sdes return (pam_err); 17889728Sdes} 17989728Sdes 18089728SdesPAM_MODULE_ENTRY("pam_lastlog"); 181