2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1992-1998
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "system/passwd.h"
22 #include "smbd/globals.h"
23 #include "../librpc/gen_ndr/netlogon.h"
24 #include "libcli/security/security.h"
26 /* what user is current? */
27 extern struct current_user current_user;
29 /****************************************************************************
30 Become the guest user without changing the security context stack.
31 ****************************************************************************/
33 bool change_to_guest(void)
37 pass = Get_Pwnam_alloc(talloc_tos(), lp_guestaccount());
43 /* MWW: From AIX FAQ patch to WU-ftpd: call initgroups before
45 initgroups(pass->pw_name, pass->pw_gid);
48 set_sec_ctx(pass->pw_uid, pass->pw_gid, 0, NULL, NULL);
50 current_user.conn = NULL;
51 current_user.vuid = UID_FIELD_INVALID;
58 /****************************************************************************
59 talloc free the conn->session_info if not used in the vuid cache.
60 ****************************************************************************/
62 static void free_conn_session_info_if_unused(connection_struct *conn)
66 for (i = 0; i < VUID_CACHE_SIZE; i++) {
67 struct vuid_cache_entry *ent;
68 ent = &conn->vuid_cache.array[i];
69 if (ent->vuid != UID_FIELD_INVALID &&
70 conn->session_info == ent->session_info) {
74 /* Not used, safe to free. */
75 TALLOC_FREE(conn->session_info);
78 /*******************************************************************
79 Check if a username is OK.
81 This sets up conn->session_info with a copy related to this vuser that
82 later code can then mess with.
83 ********************************************************************/
85 static bool check_user_ok(connection_struct *conn,
87 const struct auth_serversupplied_info *session_info,
90 bool valid_vuid = (vuid != UID_FIELD_INVALID);
96 struct vuid_cache_entry *ent;
98 for (i=0; i<VUID_CACHE_SIZE; i++) {
99 ent = &conn->vuid_cache.array[i];
100 if (ent->vuid == vuid) {
101 free_conn_session_info_if_unused(conn);
102 conn->session_info = ent->session_info;
103 conn->read_only = ent->read_only;
109 if (!user_ok_token(session_info->unix_name,
110 session_info->info3->base.domain.string,
111 session_info->security_token, snum))
114 readonly_share = is_share_read_only_for_token(
115 session_info->unix_name,
116 session_info->info3->base.domain.string,
117 session_info->security_token,
120 if (!readonly_share &&
121 !share_access_check(session_info->security_token, lp_servicename(snum),
123 /* smb.conf allows r/w, but the security descriptor denies
124 * write. Fall back to looking at readonly. */
125 readonly_share = True;
126 DEBUG(5,("falling back to read-only access-evaluation due to "
127 "security descriptor\n"));
130 if (!share_access_check(session_info->security_token, lp_servicename(snum),
132 FILE_READ_DATA : FILE_WRITE_DATA)) {
136 admin_user = token_contains_name_in_list(
137 session_info->unix_name,
138 session_info->info3->base.domain.string,
139 NULL, session_info->security_token, lp_admin_users(snum));
142 struct vuid_cache_entry *ent =
143 &conn->vuid_cache.array[conn->vuid_cache.next_entry];
145 conn->vuid_cache.next_entry =
146 (conn->vuid_cache.next_entry + 1) % VUID_CACHE_SIZE;
148 TALLOC_FREE(ent->session_info);
151 * If force_user was set, all session_info's are based on the same
152 * username-based faked one.
155 ent->session_info = copy_serverinfo(
156 conn, conn->force_user ? conn->session_info : session_info);
158 if (ent->session_info == NULL) {
159 ent->vuid = UID_FIELD_INVALID;
164 ent->read_only = readonly_share;
165 free_conn_session_info_if_unused(conn);
166 conn->session_info = ent->session_info;
169 conn->read_only = readonly_share;
171 DEBUG(2,("check_user_ok: user %s is an admin user. "
172 "Setting uid as %d\n",
173 conn->session_info->unix_name,
174 sec_initial_uid() ));
175 conn->session_info->utok.uid = sec_initial_uid();
181 /****************************************************************************
182 Clear a vuid out of the connection's vuid cache
183 This is only called on SMBulogoff.
184 ****************************************************************************/
186 void conn_clear_vuid_cache(connection_struct *conn, uint16_t vuid)
190 for (i=0; i<VUID_CACHE_SIZE; i++) {
191 struct vuid_cache_entry *ent;
193 ent = &conn->vuid_cache.array[i];
195 if (ent->vuid == vuid) {
196 ent->vuid = UID_FIELD_INVALID;
198 * We need to keep conn->session_info around
199 * if it's equal to ent->session_info as a SMBulogoff
200 * is often followed by a SMBtdis (with an invalid
201 * vuid). The debug code (or regular code in
202 * vfs_full_audit) wants to refer to the
203 * conn->session_info pointer to print debug
204 * statements. Theoretically this is a bug,
205 * as once the vuid is gone the session_info
206 * on the conn struct isn't valid any more,
207 * but there's enough code that assumes
208 * conn->session_info is never null that
209 * it's easier to hold onto the old pointer
210 * until we get a new sessionsetupX.
211 * As everything is hung off the
212 * conn pointer as a talloc context we're not
213 * leaking memory here. See bug #6315. JRA.
215 if (conn->session_info == ent->session_info) {
216 ent->session_info = NULL;
218 TALLOC_FREE(ent->session_info);
220 ent->read_only = False;
225 /****************************************************************************
226 Become the user of a connection number without changing the security context
227 stack, but modify the current_user entries.
228 ****************************************************************************/
230 bool change_to_user(connection_struct *conn, uint16 vuid)
232 const struct auth_serversupplied_info *session_info = NULL;
239 gid_t *group_list = NULL;
242 DEBUG(2,("change_to_user: Connection not open\n"));
246 vuser = get_valid_user_struct(conn->sconn, vuid);
249 * We need a separate check in security=share mode due to vuid
250 * always being UID_FIELD_INVALID. If we don't do this then
251 * in share mode security we are *always* changing uid's between
252 * SMB's - this hurts performance - Badly.
255 if((lp_security() == SEC_SHARE) && (current_user.conn == conn) &&
256 (current_user.ut.uid == conn->session_info->utok.uid)) {
257 DEBUG(4,("change_to_user: Skipping user change - already "
260 } else if ((current_user.conn == conn) &&
261 (vuser != NULL) && (current_user.vuid == vuid) &&
262 (current_user.ut.uid == vuser->session_info->utok.uid)) {
263 DEBUG(4,("change_to_user: Skipping user change - already "
270 session_info = vuser ? vuser->session_info : conn->session_info;
273 /* Invalid vuid sent - even with security = share. */
274 DEBUG(2,("change_to_user: Invalid vuid %d used on "
275 "share %s.\n",vuid, lp_servicename(snum) ));
279 if (!check_user_ok(conn, vuid, session_info, snum)) {
280 DEBUG(2,("change_to_user: SMB user %s (unix user %s, vuid %d) "
281 "not permitted access to share %s.\n",
282 session_info->sanitized_username,
283 session_info->unix_name, vuid,
284 lp_servicename(snum)));
288 /* security = share sets force_user. */
289 if (!conn->force_user && !vuser) {
290 DEBUG(2,("change_to_user: Invalid vuid used %d in accessing "
291 "share %s.\n",vuid, lp_servicename(snum) ));
296 * conn->session_info is now correctly set up with a copy we can mess
297 * with for force_group etc.
300 uid = conn->session_info->utok.uid;
301 gid = conn->session_info->utok.gid;
302 num_groups = conn->session_info->utok.ngroups;
303 group_list = conn->session_info->utok.groups;
306 * See if we should force group for this service.
307 * If so this overrides any group set in the force
311 if((group_c = *lp_force_group(snum))) {
313 SMB_ASSERT(conn->force_group_gid != (gid_t)-1);
318 * Only force group if the user is a member of
319 * the service group. Check the group memberships for
320 * this user (we already have this) to
321 * see if we should force the group.
325 for (i = 0; i < num_groups; i++) {
327 == conn->force_group_gid) {
328 conn->session_info->utok.gid =
329 conn->force_group_gid;
330 gid = conn->force_group_gid;
331 gid_to_sid(&conn->session_info->security_token
337 conn->session_info->utok.gid = conn->force_group_gid;
338 gid = conn->force_group_gid;
339 gid_to_sid(&conn->session_info->security_token->sids[1],
344 /* Now set current_user since we will immediately also call
347 current_user.ut.ngroups = num_groups;
348 current_user.ut.groups = group_list;
350 set_sec_ctx(uid, gid, current_user.ut.ngroups, current_user.ut.groups,
351 conn->session_info->security_token);
353 current_user.conn = conn;
354 current_user.vuid = vuid;
356 DEBUG(5,("change_to_user uid=(%d,%d) gid=(%d,%d)\n",
357 (int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid()));
362 /****************************************************************************
363 Go back to being root without changing the security context stack,
364 but modify the current_user entries.
365 ****************************************************************************/
367 bool change_to_root_user(void)
371 DEBUG(5,("change_to_root_user: now uid=(%d,%d) gid=(%d,%d)\n",
372 (int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid()));
374 current_user.conn = NULL;
375 current_user.vuid = UID_FIELD_INVALID;
380 /****************************************************************************
381 Become the user of an authenticated connected named pipe.
382 When this is called we are currently running as the connection
383 user. Doesn't modify current_user.
384 ****************************************************************************/
386 bool become_authenticated_pipe_user(struct pipes_struct *p)
391 set_sec_ctx(p->session_info->utok.uid, p->session_info->utok.gid,
392 p->session_info->utok.ngroups, p->session_info->utok.groups,
393 p->session_info->security_token);
398 /****************************************************************************
399 Unbecome the user of an authenticated connected named pipe.
400 When this is called we are running as the authenticated pipe
401 user and need to go back to being the connection user. Doesn't modify
403 ****************************************************************************/
405 bool unbecome_authenticated_pipe_user(void)
407 return pop_sec_ctx();
410 /****************************************************************************
411 Utility functions used by become_xxx/unbecome_xxx.
412 ****************************************************************************/
414 static void push_conn_ctx(void)
416 struct conn_ctx *ctx_p;
418 /* Check we don't overflow our stack */
420 if (conn_ctx_stack_ndx == MAX_SEC_CTX_DEPTH) {
421 DEBUG(0, ("Connection context stack overflow!\n"));
422 smb_panic("Connection context stack overflow!\n");
425 /* Store previous user context */
426 ctx_p = &conn_ctx_stack[conn_ctx_stack_ndx];
428 ctx_p->conn = current_user.conn;
429 ctx_p->vuid = current_user.vuid;
431 DEBUG(4, ("push_conn_ctx(%u) : conn_ctx_stack_ndx = %d\n",
432 (unsigned int)ctx_p->vuid, conn_ctx_stack_ndx ));
434 conn_ctx_stack_ndx++;
437 static void pop_conn_ctx(void)
439 struct conn_ctx *ctx_p;
441 /* Check for stack underflow. */
443 if (conn_ctx_stack_ndx == 0) {
444 DEBUG(0, ("Connection context stack underflow!\n"));
445 smb_panic("Connection context stack underflow!\n");
448 conn_ctx_stack_ndx--;
449 ctx_p = &conn_ctx_stack[conn_ctx_stack_ndx];
451 current_user.conn = ctx_p->conn;
452 current_user.vuid = ctx_p->vuid;
455 ctx_p->vuid = UID_FIELD_INVALID;
458 /****************************************************************************
459 Temporarily become a root user. Must match with unbecome_root(). Saves and
460 restores the connection context.
461 ****************************************************************************/
463 void become_root(void)
466 * no good way to handle push_sec_ctx() failing without changing
467 * the prototype of become_root()
469 if (!push_sec_ctx()) {
470 smb_panic("become_root: push_sec_ctx failed");
476 /* Unbecome the root user */
478 void unbecome_root(void)
484 /****************************************************************************
485 Push the current security context then force a change via change_to_user().
486 Saves and restores the connection context.
487 ****************************************************************************/
489 bool become_user(connection_struct *conn, uint16 vuid)
496 if (!change_to_user(conn, vuid)) {
505 bool unbecome_user(void)
512 /****************************************************************************
513 Return the current user we are running effectively as on this connection.
514 I'd like to make this return conn->session_info->utok.uid, but become_root()
515 doesn't alter this value.
516 ****************************************************************************/
518 uid_t get_current_uid(connection_struct *conn)
520 return current_user.ut.uid;
523 /****************************************************************************
524 Return the current group we are running effectively as on this connection.
525 I'd like to make this return conn->session_info->utok.gid, but become_root()
526 doesn't alter this value.
527 ****************************************************************************/
529 gid_t get_current_gid(connection_struct *conn)
531 return current_user.ut.gid;
534 /****************************************************************************
535 Return the UNIX token we are running effectively as on this connection.
536 I'd like to make this return &conn->session_info->utok, but become_root()
537 doesn't alter this value.
538 ****************************************************************************/
540 const struct security_unix_token *get_current_utok(connection_struct *conn)
542 return ¤t_user.ut;
545 const struct security_token *get_current_nttok(connection_struct *conn)
547 return current_user.nt_user_token;
550 uint16_t get_current_vuid(connection_struct *conn)
552 return current_user.vuid;