4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 * Copyright 2016 Toomas Soome <tsoome@me.com>
28 #pragma ident "%Z%%M% %I% %E% SMI"
31 #include <sys/types.h>
36 #include <security/pam_appl.h>
37 #include <security/pam_modules.h>
38 #include <security/pam_impl.h>
56 #include <nss_dbdefs.h>
58 #define LASTLOG "/var/adm/lastlog"
61 * pam_sm_close_session - Terminate a PAM authenticated session
65 pam_sm_close_session(pam_handle_t
*pamh
, int flags
, int argc
,
71 for (i
= 0; i
< argc
; i
++) {
72 if (strcasecmp(argv
[i
], "debug") == 0)
74 else if (strcasecmp(argv
[i
], "nowarn") != 0)
75 syslog(LOG_ERR
, "illegal option %s", argv
[i
]);
80 "pam_unix_session: inside pam_sm_close_session()");
87 pam_sm_open_session(pam_handle_t
*pamh
, int flags
, int argc
,
91 char *ttyn
, *rhost
, *user
;
95 char buffer
[NSS_BUFLEN_PASSWD
];
101 for (i
= 0; i
< argc
; i
++) {
102 if (strcasecmp(argv
[i
], "debug") == 0)
104 else if (strcasecmp(argv
[i
], "nowarn") == 0)
105 flags
= flags
| PAM_SILENT
;
107 syslog(LOG_ERR
, "illegal option %s", argv
[i
]);
112 "pam_unix_session: inside pam_sm_open_session()");
114 if ((error
= pam_get_item(pamh
, PAM_TTY
, (void **)&ttyn
))
116 (error
= pam_get_item(pamh
, PAM_USER
, (void **)&user
))
118 (error
= pam_get_item(pamh
, PAM_RHOST
, (void **)&rhost
))
123 if (user
== NULL
|| *user
== '\0')
124 return (PAM_USER_UNKNOWN
);
126 /* report error if ttyn not set */
128 return (PAM_SESSION_ERR
);
130 if (getpwnam_r(user
, &pwd
, buffer
, sizeof (buffer
)) == NULL
) {
131 return (PAM_USER_UNKNOWN
);
134 if ((fdl
= open(LASTLOG
, O_RDWR
|O_CREAT
|O_DSYNC
, 0444)) >= 0) {
136 * The value of lastlog is read by the UNIX
137 * account management module
139 offset
= (offset_t
)pwd
.pw_uid
*
140 (offset_t
)sizeof (struct lastlog
);
142 if (llseek(fdl
, offset
, SEEK_SET
) != offset
) {
144 "pam_unix_session: Can't update lastlog: uid %d "
145 "too large", pwd
.pw_uid
);
147 return (PAM_SUCCESS
);
150 * use time32_t in case of _LP64
151 * since it's written in lastlog.h
153 (void) time(&cur_time
);
155 bzero((char *)&newll
, sizeof (struct lastlog
));
157 newll
.ll_time
= (time32_t
)cur_time
;
159 newll
.ll_time
= cur_time
;
161 if ((strncmp(ttyn
, "/dev/", 5) == 0)) {
162 (void) strlcpy(newll
.ll_line
,
163 (ttyn
+ sizeof ("/dev/")-1),
164 sizeof (newll
.ll_line
));
166 (void) strlcpy(newll
.ll_line
, ttyn
,
167 sizeof (newll
.ll_line
));
170 (void) strlcpy(newll
.ll_host
, rhost
,
171 sizeof (newll
.ll_host
));
176 (void) ctime_r((const time_t *)&cur_time
, buf
,
179 syslog(LOG_DEBUG
, "pam_unix_session: "
180 "user = %s, time = %s, tty = %s, host = %s.",
181 user
, buf
, newll
.ll_line
, newll
.ll_host
);
183 if (write(fdl
, (char *)&newll
, sizeof (newll
))
185 syslog(LOG_ERR
, "pam_unix_session: Can't write "
186 "lastlog: uid %d: %m", pwd
.pw_uid
);
188 syslog(LOG_ERR
, "pam_unix_session: Can't close "
189 "lastlog: uid %d: %m", pwd
.pw_uid
);
191 return (PAM_SUCCESS
);