17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
253970ef31SToomas Soome  * Copyright 2016 Toomas Soome <tsoome@me.com>
267c478bd9Sstevel@tonic-gate  */
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate #include <strings.h>
297c478bd9Sstevel@tonic-gate #include <sys/types.h>
307c478bd9Sstevel@tonic-gate #include <sys/wait.h>
317c478bd9Sstevel@tonic-gate #include <sys/stat.h>
327c478bd9Sstevel@tonic-gate #include <fcntl.h>
337c478bd9Sstevel@tonic-gate #include <stdlib.h>
347c478bd9Sstevel@tonic-gate #include <security/pam_appl.h>
357c478bd9Sstevel@tonic-gate #include <security/pam_modules.h>
367c478bd9Sstevel@tonic-gate #include <security/pam_impl.h>
377c478bd9Sstevel@tonic-gate #include <syslog.h>
387c478bd9Sstevel@tonic-gate #include <pwd.h>
397c478bd9Sstevel@tonic-gate #include <shadow.h>
407c478bd9Sstevel@tonic-gate #include <lastlog.h>
417c478bd9Sstevel@tonic-gate #include <ctype.h>
427c478bd9Sstevel@tonic-gate #include <unistd.h>
437c478bd9Sstevel@tonic-gate #include <stdlib.h>
447c478bd9Sstevel@tonic-gate #include <stdio.h>
457c478bd9Sstevel@tonic-gate #include <libintl.h>
467c478bd9Sstevel@tonic-gate #include <signal.h>
477c478bd9Sstevel@tonic-gate #include <thread.h>
487c478bd9Sstevel@tonic-gate #include <synch.h>
497c478bd9Sstevel@tonic-gate #include <errno.h>
507c478bd9Sstevel@tonic-gate #include <time.h>
517c478bd9Sstevel@tonic-gate #include <string.h>
527c478bd9Sstevel@tonic-gate #include <crypt.h>
537c478bd9Sstevel@tonic-gate #include <assert.h>
547c478bd9Sstevel@tonic-gate #include <nss_dbdefs.h>
557c478bd9Sstevel@tonic-gate 
56*2de0a7d6SDan McDonald #define	LASTLOG		"/var/adm/lastlog"
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate /*
597c478bd9Sstevel@tonic-gate  * pam_sm_close_session	- Terminate a PAM authenticated session
607c478bd9Sstevel@tonic-gate  */
617c478bd9Sstevel@tonic-gate /*ARGSUSED*/
627c478bd9Sstevel@tonic-gate int
pam_sm_close_session(pam_handle_t * pamh,int flags,int argc,const char ** argv)637c478bd9Sstevel@tonic-gate pam_sm_close_session(pam_handle_t *pamh, int flags, int argc,
643970ef31SToomas Soome     const char **argv)
657c478bd9Sstevel@tonic-gate {
667c478bd9Sstevel@tonic-gate 	int	i;
677c478bd9Sstevel@tonic-gate 	int	debug = 0;
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate 	for (i = 0; i < argc; i++) {
707c478bd9Sstevel@tonic-gate 		if (strcasecmp(argv[i], "debug") == 0)
717c478bd9Sstevel@tonic-gate 			debug = 1;
721962723dSToomas Soome 		else if (strcasecmp(argv[i], "nowarn") != 0)
737c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, "illegal option %s", argv[i]);
747c478bd9Sstevel@tonic-gate 	}
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate 	if (debug)
777c478bd9Sstevel@tonic-gate 		syslog(LOG_DEBUG,
787c478bd9Sstevel@tonic-gate 		    "pam_unix_session: inside pam_sm_close_session()");
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate 	return (PAM_SUCCESS);
817c478bd9Sstevel@tonic-gate }
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate /*ARGSUSED*/
847c478bd9Sstevel@tonic-gate int
pam_sm_open_session(pam_handle_t * pamh,int flags,int argc,const char ** argv)857c478bd9Sstevel@tonic-gate pam_sm_open_session(pam_handle_t *pamh, int flags, int argc,
863970ef31SToomas Soome     const char **argv)
877c478bd9Sstevel@tonic-gate {
887c478bd9Sstevel@tonic-gate 	int	error;
897c478bd9Sstevel@tonic-gate 	char    *ttyn, *rhost, *user;
907c478bd9Sstevel@tonic-gate 	int	fdl;
91*2de0a7d6SDan McDonald 	struct lastlog  newll;
927c478bd9Sstevel@tonic-gate 	struct passwd pwd;
937c478bd9Sstevel@tonic-gate 	char    buffer[NSS_BUFLEN_PASSWD];
947c478bd9Sstevel@tonic-gate 	int	i;
957c478bd9Sstevel@tonic-gate 	int	debug = 0;
96*2de0a7d6SDan McDonald 	offset_t	offset;
97*2de0a7d6SDan McDonald 	time_t  cur_time;
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate 	for (i = 0; i < argc; i++) {
1007c478bd9Sstevel@tonic-gate 		if (strcasecmp(argv[i], "debug") == 0)
1017c478bd9Sstevel@tonic-gate 			debug = 1;
1023970ef31SToomas Soome 		else if (strcasecmp(argv[i], "nowarn") == 0)
1033970ef31SToomas Soome 			flags = flags | PAM_SILENT;
1047c478bd9Sstevel@tonic-gate 		else
1057c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, "illegal option %s", argv[i]);
1067c478bd9Sstevel@tonic-gate 	}
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate 	if (debug)
1097c478bd9Sstevel@tonic-gate 		syslog(LOG_DEBUG,
1107c478bd9Sstevel@tonic-gate 		    "pam_unix_session: inside pam_sm_open_session()");
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate 	if ((error = pam_get_item(pamh, PAM_TTY, (void **)&ttyn))
1137c478bd9Sstevel@tonic-gate 	    != PAM_SUCCESS ||
1147c478bd9Sstevel@tonic-gate 	    (error = pam_get_item(pamh, PAM_USER, (void **)&user))
1157c478bd9Sstevel@tonic-gate 	    != PAM_SUCCESS ||
1167c478bd9Sstevel@tonic-gate 	    (error = pam_get_item(pamh, PAM_RHOST, (void **)&rhost))
1177c478bd9Sstevel@tonic-gate 	    != PAM_SUCCESS) {
1187c478bd9Sstevel@tonic-gate 		return (error);
1197c478bd9Sstevel@tonic-gate 	}
1207c478bd9Sstevel@tonic-gate 
1217c478bd9Sstevel@tonic-gate 	if (user == NULL || *user == '\0')
1227c478bd9Sstevel@tonic-gate 		return (PAM_USER_UNKNOWN);
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate 	/* report error if ttyn not set */
1257c478bd9Sstevel@tonic-gate 	if (ttyn == NULL)
1267c478bd9Sstevel@tonic-gate 		return (PAM_SESSION_ERR);
1277c478bd9Sstevel@tonic-gate 
1287c478bd9Sstevel@tonic-gate 	if (getpwnam_r(user, &pwd, buffer, sizeof (buffer)) == NULL) {
1297c478bd9Sstevel@tonic-gate 		return (PAM_USER_UNKNOWN);
1307c478bd9Sstevel@tonic-gate 	}
1317c478bd9Sstevel@tonic-gate 
132*2de0a7d6SDan McDonald 	if ((fdl = open(LASTLOG, O_RDWR|O_CREAT|O_DSYNC, 0444)) >= 0) {
133*2de0a7d6SDan McDonald 		/*
134*2de0a7d6SDan McDonald 		 * The value of lastlog is read by the UNIX
135*2de0a7d6SDan McDonald 		 * account management module
136*2de0a7d6SDan McDonald 		 */
137*2de0a7d6SDan McDonald 		offset = (offset_t)pwd.pw_uid *
138*2de0a7d6SDan McDonald 		    (offset_t)sizeof (struct lastlog);
139*2de0a7d6SDan McDonald 
140*2de0a7d6SDan McDonald 		if (llseek(fdl, offset, SEEK_SET) != offset) {
141*2de0a7d6SDan McDonald 			syslog(LOG_ERR,
142*2de0a7d6SDan McDonald 			    "pam_unix_session: Can't update lastlog: uid %d "
143*2de0a7d6SDan McDonald 			    "too large", pwd.pw_uid);
144*2de0a7d6SDan McDonald 			(void) close(fdl);
145*2de0a7d6SDan McDonald 			return (PAM_SUCCESS);
146*2de0a7d6SDan McDonald 		}
147*2de0a7d6SDan McDonald 		/*
148*2de0a7d6SDan McDonald 		 * use time32_t in case of _LP64
149*2de0a7d6SDan McDonald 		 * since it's written in lastlog.h
150*2de0a7d6SDan McDonald 		 */
151*2de0a7d6SDan McDonald 		(void) time(&cur_time);
1526249f972SLauri Tirkkonen 
153*2de0a7d6SDan McDonald 		bzero((char *)&newll, sizeof (struct lastlog));
154*2de0a7d6SDan McDonald #ifdef _LP64
155*2de0a7d6SDan McDonald 		newll.ll_time = (time32_t)cur_time;
156*2de0a7d6SDan McDonald #else
157*2de0a7d6SDan McDonald 		newll.ll_time = cur_time;
158*2de0a7d6SDan McDonald #endif
159*2de0a7d6SDan McDonald 		if ((strncmp(ttyn, "/dev/", 5) == 0)) {
160*2de0a7d6SDan McDonald 			(void) strlcpy(newll.ll_line,
161*2de0a7d6SDan McDonald 			    (ttyn + sizeof ("/dev/")-1),
162*2de0a7d6SDan McDonald 			    sizeof (newll.ll_line));
1637c478bd9Sstevel@tonic-gate 		} else {
164*2de0a7d6SDan McDonald 			(void) strlcpy(newll.ll_line, ttyn,
165*2de0a7d6SDan McDonald 			    sizeof (newll.ll_line));
1667c478bd9Sstevel@tonic-gate 		}
167*2de0a7d6SDan McDonald 		if (rhost != NULL) {
168*2de0a7d6SDan McDonald 			(void) strlcpy(newll.ll_host, rhost,
169*2de0a7d6SDan McDonald 			    sizeof (newll.ll_host));
1707c478bd9Sstevel@tonic-gate 		}
171*2de0a7d6SDan McDonald 		if (debug) {
172*2de0a7d6SDan McDonald 			char	buf[26];
173*2de0a7d6SDan McDonald 
174*2de0a7d6SDan McDonald 			(void) ctime_r((const time_t *)&cur_time, buf,
175*2de0a7d6SDan McDonald 			    sizeof (buf));
176*2de0a7d6SDan McDonald 			buf[24] = '\000';
177*2de0a7d6SDan McDonald 			syslog(LOG_DEBUG, "pam_unix_session: "
178*2de0a7d6SDan McDonald 			    "user = %s, time = %s, tty = %s, host = %s.",
179*2de0a7d6SDan McDonald 			    user, buf, newll.ll_line, newll.ll_host);
180*2de0a7d6SDan McDonald 		}
181*2de0a7d6SDan McDonald 		if (write(fdl, (char *)&newll, sizeof (newll))
182*2de0a7d6SDan McDonald 		    != sizeof (newll))
183*2de0a7d6SDan McDonald 			syslog(LOG_ERR, "pam_unix_session: Can't write "
184*2de0a7d6SDan McDonald 			    "lastlog: uid %d: %m", pwd.pw_uid);
185*2de0a7d6SDan McDonald 		if (close(fdl) != 0)
186*2de0a7d6SDan McDonald 			syslog(LOG_ERR, "pam_unix_session: Can't close "
187*2de0a7d6SDan McDonald 			    "lastlog: uid %d: %m", pwd.pw_uid);
1887c478bd9Sstevel@tonic-gate 	}
1897c478bd9Sstevel@tonic-gate 	return (PAM_SUCCESS);
1907c478bd9Sstevel@tonic-gate }
191