4ddb856930d01f3f44485d8b16ffe43bb67dabfd
[kai/samba-autobuild/.git] / source3 / smbd / session.c
1 /* 
2    Unix SMB/CIFS implementation.
3    session handling for utmp and PAM
4
5    Copyright (C) tridge@samba.org       2001
6    Copyright (C) abartlet@samba.org     2001
7    Copyright (C) Gerald (Jerry) Carter  2006   
8    
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.
13    
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.
18    
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/>.
21 */
22
23 /* a "session" is claimed when we do a SessionSetupX operation
24    and is yielded when the corresponding vuid is destroyed.
25
26    sessions are used to populate utmp and PAM session structures
27 */
28
29 #include "includes.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "dbwrap/dbwrap.h"
33 #include "session.h"
34 #include "auth.h"
35 #include "../lib/tsocket/tsocket.h"
36 #include "../libcli/security/security.h"
37 #include "messages.h"
38
39 /********************************************************************
40  called when a session is created
41 ********************************************************************/
42
43 bool session_claim(struct smbXsrv_session *session)
44 {
45         struct auth_session_info *session_info =
46                 session->global->auth_session_info;
47         const char *username;
48         const char *hostname;
49         unsigned int id_num;
50         fstring id_str;
51
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) {
55                 return true;
56         }
57
58         id_num = session->global->session_global_id;
59
60         snprintf(id_str, sizeof(id_str), "smb/%u", id_num);
61
62         /* Make clear that we require the optional unix_token in the source3 code */
63         SMB_ASSERT(session_info->unix_token);
64
65         username = session_info->unix_info->unix_name;
66         hostname = session->global->channels[0].remote_name;
67
68         if (!smb_pam_claim_session(username, id_str, hostname)) {
69                 DEBUG(1,("pam_session rejected the session for %s [%s]\n",
70                                 username, id_str));
71                 return false;
72         }
73
74         if (lp_utmp()) {
75                 sys_utmp_claim(username, hostname, id_str, id_num);
76         }
77
78         return true;
79 }
80
81 /********************************************************************
82  called when a session is destroyed
83 ********************************************************************/
84
85 void session_yield(struct smbXsrv_session *session)
86 {
87         struct auth_session_info *session_info =
88                 session->global->auth_session_info;
89         const char *username;
90         const char *hostname;
91         unsigned int id_num;
92         fstring id_str = "";
93
94         id_num = session->global->session_global_id;
95
96         snprintf(id_str, sizeof(id_str), "smb/%u", id_num);
97
98         /* Make clear that we require the optional unix_token in the source3 code */
99         SMB_ASSERT(session_info->unix_token);
100
101         username = session_info->unix_info->unix_name;
102         hostname = session->global->channels[0].remote_name;
103
104         if (lp_utmp()) {
105                 sys_utmp_yield(username, hostname, id_str, id_num);
106         }
107
108         smb_pam_close_session(username, id_str, hostname);
109 }
110
111 /********************************************************************
112 ********************************************************************/
113
114 struct session_list {
115         TALLOC_CTX *mem_ctx;
116         int count;
117         const char *filter_user;
118         const char *filter_machine;
119         struct sessionid *sessions;
120 };
121
122 static int gather_sessioninfo(const char *key, struct sessionid *session,
123                               void *private_data)
124 {
125         struct session_list *sesslist = (struct session_list *)private_data;
126
127         /* filter the session if required */
128
129         if (sesslist->filter_user &&
130             (sesslist->filter_user[0] != '\0') &&
131             !strequal(session->username, sesslist->filter_user)) {
132                 return 0;
133         }
134
135         if (sesslist->filter_machine &&
136             (sesslist->filter_machine[0] != '\0') &&
137             !strequal(session->remote_machine,
138                       sesslist->filter_machine)) {
139                 return 0;
140         }
141
142         sesslist->sessions = talloc_realloc(
143                 sesslist->mem_ctx, sesslist->sessions, struct sessionid,
144                 sesslist->count+1);
145
146         if (!sesslist->sessions) {
147                 sesslist->count = 0;
148                 return -1;
149         }
150
151         memcpy(&sesslist->sessions[sesslist->count], session,
152                sizeof(struct sessionid));
153
154         sesslist->count++;
155
156         DEBUG(7, ("gather_sessioninfo session from %s@%s\n",
157                   session->username, session->remote_machine));
158
159         return 0;
160 }
161
162 /********************************************************************
163 ********************************************************************/
164
165 int list_sessions(TALLOC_CTX *mem_ctx, struct sessionid **session_list)
166 {
167         struct session_list sesslist;
168         NTSTATUS status;
169
170         sesslist.mem_ctx = mem_ctx;
171         sesslist.count = 0;
172         sesslist.filter_user = NULL;
173         sesslist.filter_machine = NULL;
174         sesslist.sessions = NULL;
175
176         status = sessionid_traverse_read(gather_sessioninfo, (void *) &sesslist);
177         if (!NT_STATUS_IS_OK(status)) {
178                 DEBUG(3, ("Session traverse failed\n"));
179                 SAFE_FREE(sesslist.sessions);
180                 *session_list = NULL;
181                 return 0;
182         }
183
184         *session_list = sesslist.sessions;
185         return sesslist.count;
186 }
187
188 /********************************************************************
189 find the sessions that match the given username and machine
190 ********************************************************************/
191
192 int find_sessions(TALLOC_CTX *mem_ctx, const char *username,
193                   const char *machine, struct sessionid **session_list)
194 {
195         struct session_list sesslist;
196         NTSTATUS status;
197
198         sesslist.mem_ctx = mem_ctx;
199         sesslist.count = 0;
200         sesslist.filter_user = username;
201         sesslist.filter_machine = machine;
202         sesslist.sessions = NULL;
203
204         status = sessionid_traverse_read(gather_sessioninfo, (void *)&sesslist);
205         if (!NT_STATUS_IS_OK(status)) {
206                 DEBUG(3, ("Session traverse failed: %s\n", nt_errstr(status)));
207                 TALLOC_FREE(sesslist.sessions);
208                 *session_list = NULL;
209                 return 0;
210         }
211
212         *session_list = sesslist.sessions;
213         return sesslist.count;
214 }