1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate * CDDL HEADER START
3*0Sstevel@tonic-gate *
4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
7*0Sstevel@tonic-gate * with the License.
8*0Sstevel@tonic-gate *
9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate * and limitations under the License.
13*0Sstevel@tonic-gate *
14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate *
20*0Sstevel@tonic-gate * CDDL HEADER END
21*0Sstevel@tonic-gate */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24*0Sstevel@tonic-gate * Use is subject to license terms.
25*0Sstevel@tonic-gate */
26*0Sstevel@tonic-gate
27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
28*0Sstevel@tonic-gate
29*0Sstevel@tonic-gate #include <strings.h>
30*0Sstevel@tonic-gate #include <sys/types.h>
31*0Sstevel@tonic-gate #include <sys/wait.h>
32*0Sstevel@tonic-gate #include <sys/stat.h>
33*0Sstevel@tonic-gate #include <fcntl.h>
34*0Sstevel@tonic-gate #include <stdlib.h>
35*0Sstevel@tonic-gate #include <security/pam_appl.h>
36*0Sstevel@tonic-gate #include <security/pam_modules.h>
37*0Sstevel@tonic-gate #include <security/pam_impl.h>
38*0Sstevel@tonic-gate #include <syslog.h>
39*0Sstevel@tonic-gate #include <pwd.h>
40*0Sstevel@tonic-gate #include <shadow.h>
41*0Sstevel@tonic-gate #include <lastlog.h>
42*0Sstevel@tonic-gate #include <ctype.h>
43*0Sstevel@tonic-gate #include <unistd.h>
44*0Sstevel@tonic-gate #include <stdlib.h>
45*0Sstevel@tonic-gate #include <stdio.h>
46*0Sstevel@tonic-gate #include <libintl.h>
47*0Sstevel@tonic-gate #include <signal.h>
48*0Sstevel@tonic-gate #include <thread.h>
49*0Sstevel@tonic-gate #include <synch.h>
50*0Sstevel@tonic-gate #include <errno.h>
51*0Sstevel@tonic-gate #include <time.h>
52*0Sstevel@tonic-gate #include <string.h>
53*0Sstevel@tonic-gate #include <crypt.h>
54*0Sstevel@tonic-gate #include <assert.h>
55*0Sstevel@tonic-gate #include <nss_dbdefs.h>
56*0Sstevel@tonic-gate
57*0Sstevel@tonic-gate #define LASTLOG "/var/adm/lastlog"
58*0Sstevel@tonic-gate
59*0Sstevel@tonic-gate /*
60*0Sstevel@tonic-gate * pam_sm_close_session - Terminate a PAM authenticated session
61*0Sstevel@tonic-gate */
62*0Sstevel@tonic-gate /*ARGSUSED*/
63*0Sstevel@tonic-gate int
pam_sm_close_session(pam_handle_t * pamh,int flags,int argc,const char ** argv)64*0Sstevel@tonic-gate pam_sm_close_session(pam_handle_t *pamh, int flags, int argc,
65*0Sstevel@tonic-gate const char **argv)
66*0Sstevel@tonic-gate {
67*0Sstevel@tonic-gate int i;
68*0Sstevel@tonic-gate int debug = 0;
69*0Sstevel@tonic-gate
70*0Sstevel@tonic-gate for (i = 0; i < argc; i++) {
71*0Sstevel@tonic-gate if (strcasecmp(argv[i], "debug") == 0)
72*0Sstevel@tonic-gate debug = 1;
73*0Sstevel@tonic-gate else
74*0Sstevel@tonic-gate syslog(LOG_ERR, "illegal option %s", argv[i]);
75*0Sstevel@tonic-gate }
76*0Sstevel@tonic-gate
77*0Sstevel@tonic-gate if (debug)
78*0Sstevel@tonic-gate syslog(LOG_DEBUG,
79*0Sstevel@tonic-gate "pam_unix_session: inside pam_sm_close_session()");
80*0Sstevel@tonic-gate
81*0Sstevel@tonic-gate return (PAM_SUCCESS);
82*0Sstevel@tonic-gate }
83*0Sstevel@tonic-gate
84*0Sstevel@tonic-gate /*ARGSUSED*/
85*0Sstevel@tonic-gate int
pam_sm_open_session(pam_handle_t * pamh,int flags,int argc,const char ** argv)86*0Sstevel@tonic-gate pam_sm_open_session(pam_handle_t *pamh, int flags, int argc,
87*0Sstevel@tonic-gate const char **argv)
88*0Sstevel@tonic-gate {
89*0Sstevel@tonic-gate int error;
90*0Sstevel@tonic-gate char *ttyn, *rhost, *user;
91*0Sstevel@tonic-gate int fdl;
92*0Sstevel@tonic-gate struct lastlog newll;
93*0Sstevel@tonic-gate struct passwd pwd;
94*0Sstevel@tonic-gate char buffer[NSS_BUFLEN_PASSWD];
95*0Sstevel@tonic-gate int i;
96*0Sstevel@tonic-gate int debug = 0;
97*0Sstevel@tonic-gate offset_t offset;
98*0Sstevel@tonic-gate time_t cur_time;
99*0Sstevel@tonic-gate
100*0Sstevel@tonic-gate for (i = 0; i < argc; i++) {
101*0Sstevel@tonic-gate if (strcasecmp(argv[i], "debug") == 0)
102*0Sstevel@tonic-gate debug = 1;
103*0Sstevel@tonic-gate else
104*0Sstevel@tonic-gate syslog(LOG_ERR, "illegal option %s", argv[i]);
105*0Sstevel@tonic-gate }
106*0Sstevel@tonic-gate
107*0Sstevel@tonic-gate if (debug)
108*0Sstevel@tonic-gate syslog(LOG_DEBUG,
109*0Sstevel@tonic-gate "pam_unix_session: inside pam_sm_open_session()");
110*0Sstevel@tonic-gate
111*0Sstevel@tonic-gate if ((error = pam_get_item(pamh, PAM_TTY, (void **)&ttyn))
112*0Sstevel@tonic-gate != PAM_SUCCESS ||
113*0Sstevel@tonic-gate (error = pam_get_item(pamh, PAM_USER, (void **)&user))
114*0Sstevel@tonic-gate != PAM_SUCCESS ||
115*0Sstevel@tonic-gate (error = pam_get_item(pamh, PAM_RHOST, (void **)&rhost))
116*0Sstevel@tonic-gate != PAM_SUCCESS) {
117*0Sstevel@tonic-gate return (error);
118*0Sstevel@tonic-gate }
119*0Sstevel@tonic-gate
120*0Sstevel@tonic-gate if (user == NULL || *user == '\0')
121*0Sstevel@tonic-gate return (PAM_USER_UNKNOWN);
122*0Sstevel@tonic-gate
123*0Sstevel@tonic-gate /* report error if ttyn not set */
124*0Sstevel@tonic-gate if (ttyn == NULL)
125*0Sstevel@tonic-gate return (PAM_SESSION_ERR);
126*0Sstevel@tonic-gate
127*0Sstevel@tonic-gate if (getpwnam_r(user, &pwd, buffer, sizeof (buffer)) == NULL) {
128*0Sstevel@tonic-gate return (PAM_USER_UNKNOWN);
129*0Sstevel@tonic-gate }
130*0Sstevel@tonic-gate
131*0Sstevel@tonic-gate if ((fdl = open(LASTLOG, O_RDWR|O_CREAT|O_DSYNC, 0444)) >= 0) {
132*0Sstevel@tonic-gate /*
133*0Sstevel@tonic-gate * The value of lastlog is read by the UNIX
134*0Sstevel@tonic-gate * account management module
135*0Sstevel@tonic-gate */
136*0Sstevel@tonic-gate offset = (offset_t)pwd.pw_uid *
137*0Sstevel@tonic-gate (offset_t)sizeof (struct lastlog);
138*0Sstevel@tonic-gate
139*0Sstevel@tonic-gate if (llseek(fdl, offset, SEEK_SET) != offset) {
140*0Sstevel@tonic-gate syslog(LOG_ERR,
141*0Sstevel@tonic-gate "pam_unix_session: Can't update lastlog: uid %d "
142*0Sstevel@tonic-gate "too large", pwd.pw_uid);
143*0Sstevel@tonic-gate (void) close(fdl);
144*0Sstevel@tonic-gate return (PAM_SUCCESS);
145*0Sstevel@tonic-gate }
146*0Sstevel@tonic-gate /*
147*0Sstevel@tonic-gate * use time32_t in case of _LP64
148*0Sstevel@tonic-gate * since it's written in lastlog.h
149*0Sstevel@tonic-gate */
150*0Sstevel@tonic-gate (void) time(&cur_time);
151*0Sstevel@tonic-gate
152*0Sstevel@tonic-gate bzero((char *)&newll, sizeof (struct lastlog));
153*0Sstevel@tonic-gate #ifdef _LP64
154*0Sstevel@tonic-gate newll.ll_time = (time32_t)cur_time;
155*0Sstevel@tonic-gate #else
156*0Sstevel@tonic-gate newll.ll_time = cur_time;
157*0Sstevel@tonic-gate #endif
158*0Sstevel@tonic-gate if ((strncmp(ttyn, "/dev/", 5) == 0)) {
159*0Sstevel@tonic-gate (void) strlcpy(newll.ll_line,
160*0Sstevel@tonic-gate (ttyn + sizeof ("/dev/")-1),
161*0Sstevel@tonic-gate sizeof (newll.ll_line));
162*0Sstevel@tonic-gate } else {
163*0Sstevel@tonic-gate (void) strlcpy(newll.ll_line, ttyn,
164*0Sstevel@tonic-gate sizeof (newll.ll_line));
165*0Sstevel@tonic-gate }
166*0Sstevel@tonic-gate if (rhost != NULL) {
167*0Sstevel@tonic-gate (void) strlcpy(newll.ll_host, rhost,
168*0Sstevel@tonic-gate sizeof (newll.ll_host));
169*0Sstevel@tonic-gate }
170*0Sstevel@tonic-gate if (debug) {
171*0Sstevel@tonic-gate char buf[26];
172*0Sstevel@tonic-gate
173*0Sstevel@tonic-gate (void) ctime_r((const time_t *)&cur_time, buf,
174*0Sstevel@tonic-gate sizeof (buf));
175*0Sstevel@tonic-gate buf[24] = '\000';
176*0Sstevel@tonic-gate syslog(LOG_DEBUG, "pam_unix_session: "
177*0Sstevel@tonic-gate "user = %s, time = %s, tty = %s, host = %s.",
178*0Sstevel@tonic-gate user, buf, newll.ll_line, newll.ll_host);
179*0Sstevel@tonic-gate }
180*0Sstevel@tonic-gate if (write(fdl, (char *)&newll, sizeof (newll))
181*0Sstevel@tonic-gate != sizeof (newll))
182*0Sstevel@tonic-gate syslog(LOG_ERR, "pam_unix_session: Can't write "
183*0Sstevel@tonic-gate "lastlog: uid %d: %m", pwd.pw_uid);
184*0Sstevel@tonic-gate if (close(fdl) != 0)
185*0Sstevel@tonic-gate syslog(LOG_ERR, "pam_unix_session: Can't close "
186*0Sstevel@tonic-gate "lastlog: uid %d: %m", pwd.pw_uid);
187*0Sstevel@tonic-gate }
188*0Sstevel@tonic-gate return (PAM_SUCCESS);
189*0Sstevel@tonic-gate }
190