2 Unix SMB/CIFS implementation.
3 session handling for utmp and PAM
5 Copyright (C) tridge@samba.org 2001
6 Copyright (C) abartlet@samba.org 2001
7 Copyright (C) Gerald (Jerry) Carter 2006
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 /* a "session" is claimed when we do a SessionSetupX operation
24 and is yielded when the corresponding vuid is destroyed.
26 sessions are used to populate utmp and PAM session structures
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "dbwrap/dbwrap.h"
35 #include "../lib/tsocket/tsocket.h"
36 #include "../libcli/security/security.h"
39 /********************************************************************
40 called when a session is created
41 ********************************************************************/
43 bool session_claim(struct smbXsrv_session
*session
)
45 struct auth_session_info
*session_info
=
46 session
->global
->auth_session_info
;
52 /* don't register sessions for the guest user - its just too
53 expensive to go through pam session code for browsing etc */
54 if (security_session_user_level(session_info
, NULL
) < SECURITY_USER
) {
58 id_num
= session
->global
->session_global_id
;
60 snprintf(id_str
, sizeof(id_str
), "smb/%u", id_num
);
62 /* Make clear that we require the optional unix_token in the source3 code */
63 SMB_ASSERT(session_info
->unix_token
);
65 username
= session_info
->unix_info
->unix_name
;
66 hostname
= session
->global
->channels
[0].remote_name
;
68 if (!smb_pam_claim_session(username
, id_str
, hostname
)) {
69 DEBUG(1,("pam_session rejected the session for %s [%s]\n",
75 sys_utmp_claim(username
, hostname
, id_str
, id_num
);
81 /********************************************************************
82 called when a session is destroyed
83 ********************************************************************/
85 void session_yield(struct smbXsrv_session
*session
)
87 struct auth_session_info
*session_info
=
88 session
->global
->auth_session_info
;
94 id_num
= session
->global
->session_global_id
;
96 snprintf(id_str
, sizeof(id_str
), "smb/%u", id_num
);
98 /* Make clear that we require the optional unix_token in the source3 code */
99 SMB_ASSERT(session_info
->unix_token
);
101 username
= session_info
->unix_info
->unix_name
;
102 hostname
= session
->global
->channels
[0].remote_name
;
105 sys_utmp_yield(username
, hostname
, id_str
, id_num
);
108 smb_pam_close_session(username
, id_str
, hostname
);
111 /********************************************************************
112 ********************************************************************/
114 struct session_list
{
117 const char *filter_user
;
118 const char *filter_machine
;
119 struct sessionid
*sessions
;
122 static int gather_sessioninfo(const char *key
, struct sessionid
*session
,
125 struct session_list
*sesslist
= (struct session_list
*)private_data
;
127 /* filter the session if required */
129 if (sesslist
->filter_user
&&
130 (sesslist
->filter_user
[0] != '\0') &&
131 !strequal(session
->username
, sesslist
->filter_user
)) {
135 if (sesslist
->filter_machine
&&
136 (sesslist
->filter_machine
[0] != '\0') &&
137 !strequal(session
->remote_machine
,
138 sesslist
->filter_machine
)) {
142 if (!process_exists(session
->pid
)) {
146 sesslist
->sessions
= talloc_realloc(
147 sesslist
->mem_ctx
, sesslist
->sessions
, struct sessionid
,
150 if (!sesslist
->sessions
) {
155 memcpy(&sesslist
->sessions
[sesslist
->count
], session
,
156 sizeof(struct sessionid
));
160 DEBUG(7, ("gather_sessioninfo session from %s@%s\n",
161 session
->username
, session
->remote_machine
));
166 /********************************************************************
167 ********************************************************************/
169 int list_sessions(TALLOC_CTX
*mem_ctx
, struct sessionid
**session_list
)
171 struct session_list sesslist
;
174 sesslist
.mem_ctx
= mem_ctx
;
176 sesslist
.filter_user
= NULL
;
177 sesslist
.filter_machine
= NULL
;
178 sesslist
.sessions
= NULL
;
180 status
= sessionid_traverse_read(gather_sessioninfo
, (void *) &sesslist
);
181 if (!NT_STATUS_IS_OK(status
)) {
182 DBG_ERR("Session traverse failed: %s\n", nt_errstr(status
));
183 TALLOC_FREE(sesslist
.sessions
);
184 *session_list
= NULL
;
188 *session_list
= sesslist
.sessions
;
189 return sesslist
.count
;
192 /********************************************************************
193 find the sessions that match the given username and machine
194 ********************************************************************/
196 int find_sessions(TALLOC_CTX
*mem_ctx
, const char *username
,
197 const char *machine
, struct sessionid
**session_list
)
199 struct session_list sesslist
;
202 sesslist
.mem_ctx
= mem_ctx
;
204 sesslist
.filter_user
= username
;
205 sesslist
.filter_machine
= machine
;
206 sesslist
.sessions
= NULL
;
208 status
= sessionid_traverse_read(gather_sessioninfo
, (void *)&sesslist
);
209 if (!NT_STATUS_IS_OK(status
)) {
210 DEBUG(3, ("Session traverse failed: %s\n", nt_errstr(status
)));
211 TALLOC_FREE(sesslist
.sessions
);
212 *session_list
= NULL
;
216 *session_list
= sesslist
.sessions
;
217 return sesslist
.count
;