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> 50230952Sed 51230952Sed#include <paths.h> 5289728Sdes#include <pwd.h> 53202566Sed#include <stdlib.h> 54202566Sed#include <string.h> 5589728Sdes#include <time.h> 56202566Sed#include <unistd.h> 57202211Sed#include <utmpx.h> 5889728Sdes 5989728Sdes#define PAM_SM_SESSION 6089728Sdes 6190229Sdes#include <security/pam_appl.h> 6289728Sdes#include <security/pam_modules.h> 6390229Sdes#include <security/pam_mod_misc.h> 6489728Sdes 65202566Sed#define PAM_UTMPX_ID "utmpx_id" 66202566Sed 6789728SdesPAM_EXTERN int 6894564Sdespam_sm_open_session(pam_handle_t *pamh, int flags, 6994564Sdes int argc __unused, const char *argv[] __unused) 7089728Sdes{ 7189728Sdes struct passwd *pwd; 72202566Sed struct utmpx *utx, utl; 73106966Speter time_t t; 74123448Sdes const char *user; 75123448Sdes const void *rhost, *tty; 76202566Sed char *id; 77200413Sed int pam_err; 7889728Sdes 7994564Sdes pam_err = pam_get_user(pamh, &user, NULL); 8089728Sdes if (pam_err != PAM_SUCCESS) 8194564Sdes return (pam_err); 8289728Sdes if (user == NULL || (pwd = getpwnam(user)) == NULL) 8394564Sdes return (PAM_SERVICE_ERR); 8489728Sdes PAM_LOG("Got user: %s", user); 8589728Sdes 86123448Sdes pam_err = pam_get_item(pamh, PAM_RHOST, &rhost); 87161209Sdes if (pam_err != PAM_SUCCESS) { 88161209Sdes PAM_LOG("No PAM_RHOST"); 8997148Sdes goto err; 90161209Sdes } 91123448Sdes pam_err = pam_get_item(pamh, PAM_TTY, &tty); 92161209Sdes if (pam_err != PAM_SUCCESS) { 93161209Sdes PAM_LOG("No PAM_TTY"); 9497148Sdes goto err; 95161209Sdes } 9697625Sdes if (tty == NULL) { 97161209Sdes PAM_LOG("No PAM_TTY"); 9897625Sdes pam_err = PAM_SERVICE_ERR; 9997625Sdes goto err; 10097625Sdes } 101230952Sed /* Strip /dev/ component. */ 102230952Sed if (strncmp(tty, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0) 103230952Sed tty = (const char *)tty + sizeof(_PATH_DEV) - 1; 10494564Sdes 10589728Sdes if ((flags & PAM_SILENT) == 0) { 106202211Sed if (setutxdb(UTXDB_LASTLOGIN, NULL) != 0) { 107202211Sed PAM_LOG("Failed to open lastlogin database"); 108200413Sed } else { 109202211Sed utx = getutxuser(user); 110200413Sed if (utx != NULL && utx->ut_type == USER_PROCESS) { 111200413Sed t = utx->ut_tv.tv_sec; 112200413Sed if (*utx->ut_host != '\0') 113200413Sed pam_info(pamh, "Last login: %.*s from %s", 114200413Sed 24 - 5, ctime(&t), utx->ut_host); 115200413Sed else 116200413Sed pam_info(pamh, "Last login: %.*s on %s", 117200413Sed 24 - 5, ctime(&t), utx->ut_line); 118200413Sed } 119202211Sed endutxent(); 12089728Sdes } 12189728Sdes } 12294564Sdes 123202566Sed id = malloc(sizeof utl.ut_id); 124202566Sed if (id == NULL) { 125202566Sed pam_err = PAM_SERVICE_ERR; 126202566Sed goto err; 127202566Sed } 128202566Sed arc4random_buf(id, sizeof utl.ut_id); 12994564Sdes 130202566Sed pam_err = pam_set_data(pamh, PAM_UTMPX_ID, id, openpam_free_data); 131202566Sed if (pam_err != PAM_SUCCESS) { 132202566Sed free(id); 133202566Sed goto err; 134202566Sed } 135202566Sed 136202566Sed memset(&utl, 0, sizeof utl); 137202566Sed utl.ut_type = USER_PROCESS; 138202566Sed memcpy(utl.ut_id, id, sizeof utl.ut_id); 139202566Sed strncpy(utl.ut_user, user, sizeof utl.ut_user); 140202566Sed strncpy(utl.ut_line, tty, sizeof utl.ut_line); 141202566Sed if (rhost != NULL) 142202566Sed strncpy(utl.ut_host, rhost, sizeof utl.ut_host); 143202566Sed utl.ut_pid = getpid(); 144202566Sed gettimeofday(&utl.ut_tv, NULL); 145202566Sed pututxline(&utl); 146202566Sed 14796192Sdes return (PAM_SUCCESS); 14894564Sdes 14997148Sdeserr: 15096192Sdes if (openpam_get_option(pamh, "no_fail")) 15196192Sdes return (PAM_SUCCESS); 15297148Sdes return (pam_err); 15389728Sdes} 15489728Sdes 15589728SdesPAM_EXTERN int 156200413Sedpam_sm_close_session(pam_handle_t *pamh, int flags __unused, 15794564Sdes int argc __unused, const char *argv[] __unused) 15889728Sdes{ 159202566Sed struct utmpx utl; 160202566Sed const void *id; 161171544Sdes int pam_err; 16289728Sdes 163202566Sed pam_err = pam_get_data(pamh, PAM_UTMPX_ID, (const void **)&id); 164171544Sdes if (pam_err != PAM_SUCCESS) 165171544Sdes goto err; 166202566Sed 167202566Sed memset(&utl, 0, sizeof utl); 168202566Sed utl.ut_type = DEAD_PROCESS; 169202566Sed memcpy(utl.ut_id, id, sizeof utl.ut_id); 170202566Sed utl.ut_pid = getpid(); 171202566Sed gettimeofday(&utl.ut_tv, NULL); 172202566Sed pututxline(&utl); 173202566Sed 174171543Sdes return (PAM_SUCCESS); 175171544Sdes 176171544Sdes err: 177171544Sdes if (openpam_get_option(pamh, "no_fail")) 178171544Sdes return (PAM_SUCCESS); 179171544Sdes return (pam_err); 18089728Sdes} 18189728Sdes 18289728SdesPAM_MODULE_ENTRY("pam_lastlog"); 183