/src/samba/source3/smbd/session.c
Line | Count | Source (jump to first uncovered line) |
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 | 0 | { |
45 | 0 | struct auth_session_info *session_info = |
46 | 0 | session->global->auth_session_info; |
47 | 0 | const char *username; |
48 | 0 | const char *hostname; |
49 | 0 | unsigned int id_num; |
50 | 0 | 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 | 0 | if (security_session_user_level(session_info, NULL) < SECURITY_USER) { |
55 | 0 | return true; |
56 | 0 | } |
57 | | |
58 | 0 | id_num = session->global->session_global_id; |
59 | |
|
60 | 0 | 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 | 0 | SMB_ASSERT(session_info->unix_token); |
64 | | |
65 | 0 | username = session_info->unix_info->unix_name; |
66 | 0 | hostname = session->global->channels[0].remote_name; |
67 | |
|
68 | 0 | if (!smb_pam_claim_session(username, id_str, hostname)) { |
69 | 0 | DEBUG(1,("pam_session rejected the session for %s [%s]\n", |
70 | 0 | username, id_str)); |
71 | 0 | return false; |
72 | 0 | } |
73 | | |
74 | 0 | if (lp_utmp()) { |
75 | 0 | sys_utmp_claim(username, hostname, id_str, id_num); |
76 | 0 | } |
77 | |
|
78 | 0 | return true; |
79 | 0 | } |
80 | | |
81 | | /******************************************************************** |
82 | | called when a session is destroyed |
83 | | ********************************************************************/ |
84 | | |
85 | | void session_yield(struct smbXsrv_session *session) |
86 | 0 | { |
87 | 0 | struct auth_session_info *session_info = |
88 | 0 | session->global->auth_session_info; |
89 | 0 | const char *username; |
90 | 0 | const char *hostname; |
91 | 0 | unsigned int id_num; |
92 | 0 | fstring id_str = ""; |
93 | |
|
94 | 0 | id_num = session->global->session_global_id; |
95 | |
|
96 | 0 | 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 | 0 | SMB_ASSERT(session_info->unix_token); |
100 | | |
101 | 0 | username = session_info->unix_info->unix_name; |
102 | 0 | hostname = session->global->channels[0].remote_name; |
103 | |
|
104 | 0 | if (lp_utmp()) { |
105 | 0 | sys_utmp_yield(username, hostname, id_str, id_num); |
106 | 0 | } |
107 | |
|
108 | 0 | smb_pam_close_session(username, id_str, hostname); |
109 | 0 | } |
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 | 0 | { |
125 | 0 | struct session_list *sesslist = (struct session_list *)private_data; |
126 | | |
127 | | /* filter the session if required */ |
128 | |
|
129 | 0 | if (sesslist->filter_user && |
130 | 0 | (sesslist->filter_user[0] != '\0') && |
131 | 0 | !strequal(session->username, sesslist->filter_user)) { |
132 | 0 | return 0; |
133 | 0 | } |
134 | | |
135 | 0 | if (sesslist->filter_machine && |
136 | 0 | (sesslist->filter_machine[0] != '\0') && |
137 | 0 | !strequal(session->remote_machine, |
138 | 0 | sesslist->filter_machine)) { |
139 | 0 | return 0; |
140 | 0 | } |
141 | | |
142 | 0 | if (!process_exists(session->pid)) { |
143 | 0 | return 0; |
144 | 0 | } |
145 | | |
146 | 0 | sesslist->sessions = talloc_realloc( |
147 | 0 | sesslist->mem_ctx, sesslist->sessions, struct sessionid, |
148 | 0 | sesslist->count+1); |
149 | |
|
150 | 0 | if (!sesslist->sessions) { |
151 | 0 | sesslist->count = 0; |
152 | 0 | return -1; |
153 | 0 | } |
154 | | |
155 | 0 | memcpy(&sesslist->sessions[sesslist->count], session, |
156 | 0 | sizeof(struct sessionid)); |
157 | |
|
158 | 0 | sesslist->count++; |
159 | |
|
160 | 0 | DEBUG(7, ("gather_sessioninfo session from %s@%s\n", |
161 | 0 | session->username, session->remote_machine)); |
162 | |
|
163 | 0 | return 0; |
164 | 0 | } |
165 | | |
166 | | /******************************************************************** |
167 | | ********************************************************************/ |
168 | | |
169 | | int list_sessions(TALLOC_CTX *mem_ctx, struct sessionid **session_list) |
170 | 0 | { |
171 | 0 | struct session_list sesslist; |
172 | 0 | NTSTATUS status; |
173 | |
|
174 | 0 | sesslist.mem_ctx = mem_ctx; |
175 | 0 | sesslist.count = 0; |
176 | 0 | sesslist.filter_user = NULL; |
177 | 0 | sesslist.filter_machine = NULL; |
178 | 0 | sesslist.sessions = NULL; |
179 | |
|
180 | 0 | status = sessionid_traverse_read(gather_sessioninfo, (void *) &sesslist); |
181 | 0 | if (!NT_STATUS_IS_OK(status)) { |
182 | 0 | DBG_ERR("Session traverse failed: %s\n", nt_errstr(status)); |
183 | 0 | TALLOC_FREE(sesslist.sessions); |
184 | 0 | *session_list = NULL; |
185 | 0 | return 0; |
186 | 0 | } |
187 | | |
188 | 0 | *session_list = sesslist.sessions; |
189 | 0 | return sesslist.count; |
190 | 0 | } |
191 | | |
192 | | /******************************************************************** |
193 | | find the sessions that match the given username and machine |
194 | | ********************************************************************/ |
195 | | |
196 | | int find_sessions(TALLOC_CTX *mem_ctx, const char *username, |
197 | | const char *machine, struct sessionid **session_list) |
198 | 0 | { |
199 | 0 | struct session_list sesslist; |
200 | 0 | NTSTATUS status; |
201 | |
|
202 | 0 | sesslist.mem_ctx = mem_ctx; |
203 | 0 | sesslist.count = 0; |
204 | 0 | sesslist.filter_user = username; |
205 | 0 | sesslist.filter_machine = machine; |
206 | 0 | sesslist.sessions = NULL; |
207 | |
|
208 | 0 | status = sessionid_traverse_read(gather_sessioninfo, (void *)&sesslist); |
209 | 0 | if (!NT_STATUS_IS_OK(status)) { |
210 | 0 | DEBUG(3, ("Session traverse failed: %s\n", nt_errstr(status))); |
211 | 0 | TALLOC_FREE(sesslist.sessions); |
212 | 0 | *session_list = NULL; |
213 | 0 | return 0; |
214 | 0 | } |
215 | | |
216 | 0 | *session_list = sesslist.sessions; |
217 | 0 | return sesslist.count; |
218 | 0 | } |