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/smbd.h"
23 #include "smbd/globals.h"
24 #include "../librpc/gen_ndr/netlogon.h"
25 #include "libcli/security/security.h"
26 #include "passdb/lookup_sid.h"
30 /* what user is current? */
31 extern struct current_user current_user
;
33 /****************************************************************************
34 Become the guest user without changing the security context stack.
35 ****************************************************************************/
37 bool change_to_guest(void)
41 pass
= Get_Pwnam_alloc(talloc_tos(), lp_guestaccount());
47 /* MWW: From AIX FAQ patch to WU-ftpd: call initgroups before
49 initgroups(pass
->pw_name
, pass
->pw_gid
);
52 set_sec_ctx(pass
->pw_uid
, pass
->pw_gid
, 0, NULL
, NULL
);
54 current_user
.conn
= NULL
;
55 current_user
.vuid
= UID_FIELD_INVALID
;
62 /****************************************************************************
63 talloc free the conn->session_info if not used in the vuid cache.
64 ****************************************************************************/
66 static void free_conn_session_info_if_unused(connection_struct
*conn
)
70 for (i
= 0; i
< VUID_CACHE_SIZE
; i
++) {
71 struct vuid_cache_entry
*ent
;
72 ent
= &conn
->vuid_cache
.array
[i
];
73 if (ent
->vuid
!= UID_FIELD_INVALID
&&
74 conn
->session_info
== ent
->session_info
) {
78 /* Not used, safe to free. */
79 TALLOC_FREE(conn
->session_info
);
82 /*******************************************************************
83 Check if a username is OK.
85 This sets up conn->session_info with a copy related to this vuser that
86 later code can then mess with.
87 ********************************************************************/
89 static bool check_user_ok(connection_struct
*conn
,
91 const struct auth_serversupplied_info
*session_info
,
94 bool valid_vuid
= (vuid
!= UID_FIELD_INVALID
);
100 struct vuid_cache_entry
*ent
;
102 for (i
=0; i
<VUID_CACHE_SIZE
; i
++) {
103 ent
= &conn
->vuid_cache
.array
[i
];
104 if (ent
->vuid
== vuid
) {
105 free_conn_session_info_if_unused(conn
);
106 conn
->session_info
= ent
->session_info
;
107 conn
->read_only
= ent
->read_only
;
113 if (!user_ok_token(session_info
->unix_name
,
114 session_info
->info3
->base
.domain
.string
,
115 session_info
->security_token
, snum
))
118 readonly_share
= is_share_read_only_for_token(
119 session_info
->unix_name
,
120 session_info
->info3
->base
.domain
.string
,
121 session_info
->security_token
,
124 if (!readonly_share
&&
125 !share_access_check(session_info
->security_token
, lp_servicename(snum
),
127 /* smb.conf allows r/w, but the security descriptor denies
128 * write. Fall back to looking at readonly. */
129 readonly_share
= True
;
130 DEBUG(5,("falling back to read-only access-evaluation due to "
131 "security descriptor\n"));
134 if (!share_access_check(session_info
->security_token
, lp_servicename(snum
),
136 FILE_READ_DATA
: FILE_WRITE_DATA
)) {
140 admin_user
= token_contains_name_in_list(
141 session_info
->unix_name
,
142 session_info
->info3
->base
.domain
.string
,
143 NULL
, session_info
->security_token
, lp_admin_users(snum
));
146 struct vuid_cache_entry
*ent
=
147 &conn
->vuid_cache
.array
[conn
->vuid_cache
.next_entry
];
149 conn
->vuid_cache
.next_entry
=
150 (conn
->vuid_cache
.next_entry
+ 1) % VUID_CACHE_SIZE
;
152 TALLOC_FREE(ent
->session_info
);
155 * If force_user was set, all session_info's are based on the same
156 * username-based faked one.
159 ent
->session_info
= copy_serverinfo(
160 conn
, conn
->force_user
? conn
->session_info
: session_info
);
162 if (ent
->session_info
== NULL
) {
163 ent
->vuid
= UID_FIELD_INVALID
;
168 ent
->read_only
= readonly_share
;
169 free_conn_session_info_if_unused(conn
);
170 conn
->session_info
= ent
->session_info
;
173 conn
->read_only
= readonly_share
;
175 DEBUG(2,("check_user_ok: user %s is an admin user. "
176 "Setting uid as %d\n",
177 conn
->session_info
->unix_name
,
178 sec_initial_uid() ));
179 conn
->session_info
->utok
.uid
= sec_initial_uid();
185 /****************************************************************************
186 Clear a vuid out of the connection's vuid cache
187 This is only called on SMBulogoff.
188 ****************************************************************************/
190 void conn_clear_vuid_cache(connection_struct
*conn
, uint16_t vuid
)
194 for (i
=0; i
<VUID_CACHE_SIZE
; i
++) {
195 struct vuid_cache_entry
*ent
;
197 ent
= &conn
->vuid_cache
.array
[i
];
199 if (ent
->vuid
== vuid
) {
200 ent
->vuid
= UID_FIELD_INVALID
;
202 * We need to keep conn->session_info around
203 * if it's equal to ent->session_info as a SMBulogoff
204 * is often followed by a SMBtdis (with an invalid
205 * vuid). The debug code (or regular code in
206 * vfs_full_audit) wants to refer to the
207 * conn->session_info pointer to print debug
208 * statements. Theoretically this is a bug,
209 * as once the vuid is gone the session_info
210 * on the conn struct isn't valid any more,
211 * but there's enough code that assumes
212 * conn->session_info is never null that
213 * it's easier to hold onto the old pointer
214 * until we get a new sessionsetupX.
215 * As everything is hung off the
216 * conn pointer as a talloc context we're not
217 * leaking memory here. See bug #6315. JRA.
219 if (conn
->session_info
== ent
->session_info
) {
220 ent
->session_info
= NULL
;
222 TALLOC_FREE(ent
->session_info
);
224 ent
->read_only
= False
;
229 /****************************************************************************
230 Become the user of a connection number without changing the security context
231 stack, but modify the current_user entries.
232 ****************************************************************************/
234 static bool change_to_user_internal(connection_struct
*conn
,
235 const struct auth_serversupplied_info
*session_info
,
243 gid_t
*group_list
= NULL
;
248 ok
= check_user_ok(conn
, vuid
, session_info
, snum
);
250 DEBUG(2,("SMB user %s (unix user %s) "
251 "not permitted access to share %s.\n",
252 session_info
->sanitized_username
,
253 session_info
->unix_name
,
254 lp_servicename(snum
)));
258 uid
= conn
->session_info
->utok
.uid
;
259 gid
= conn
->session_info
->utok
.gid
;
260 num_groups
= conn
->session_info
->utok
.ngroups
;
261 group_list
= conn
->session_info
->utok
.groups
;
264 * See if we should force group for this service. If so this overrides
265 * any group set in the force user code.
267 if((group_c
= *lp_force_group(snum
))) {
269 SMB_ASSERT(conn
->force_group_gid
!= (gid_t
)-1);
271 if (group_c
== '+') {
275 * Only force group if the user is a member of the
276 * service group. Check the group memberships for this
277 * user (we already have this) to see if we should force
280 for (i
= 0; i
< num_groups
; i
++) {
281 if (group_list
[i
] == conn
->force_group_gid
) {
282 conn
->session_info
->utok
.gid
=
283 conn
->force_group_gid
;
284 gid
= conn
->force_group_gid
;
285 gid_to_sid(&conn
->session_info
->security_token
291 conn
->session_info
->utok
.gid
= conn
->force_group_gid
;
292 gid
= conn
->force_group_gid
;
293 gid_to_sid(&conn
->session_info
->security_token
->sids
[1],
298 /*Set current_user since we will immediately also call set_sec_ctx() */
299 current_user
.ut
.ngroups
= num_groups
;
300 current_user
.ut
.groups
= group_list
;
304 current_user
.ut
.ngroups
,
305 current_user
.ut
.groups
,
306 conn
->session_info
->security_token
);
308 current_user
.conn
= conn
;
309 current_user
.vuid
= vuid
;
311 DEBUG(5, ("Impersonated user: uid=(%d,%d), gid=(%d,%d)\n",
320 bool change_to_user(connection_struct
*conn
, uint16_t vuid
)
322 const struct auth_serversupplied_info
*session_info
= NULL
;
324 int snum
= SNUM(conn
);
327 DEBUG(2,("Connection not open\n"));
331 vuser
= get_valid_user_struct(conn
->sconn
, vuid
);
334 * We need a separate check in security=share mode due to vuid
335 * always being UID_FIELD_INVALID. If we don't do this then
336 * in share mode security we are *always* changing uid's between
337 * SMB's - this hurts performance - Badly.
340 if((lp_security() == SEC_SHARE
) && (current_user
.conn
== conn
) &&
341 (current_user
.ut
.uid
== conn
->session_info
->utok
.uid
)) {
342 DEBUG(4,("Skipping user change - already "
345 } else if ((current_user
.conn
== conn
) &&
346 (vuser
!= NULL
) && (current_user
.vuid
== vuid
) &&
347 (current_user
.ut
.uid
== vuser
->session_info
->utok
.uid
)) {
348 DEBUG(4,("Skipping user change - already "
353 session_info
= vuser
? vuser
->session_info
: conn
->session_info
;
355 if (session_info
== NULL
) {
356 /* Invalid vuid sent - even with security = share. */
357 DEBUG(2,("Invalid vuid %d used on "
358 "share %s.\n", vuid
, lp_servicename(snum
) ));
362 /* security = share sets force_user. */
363 if (!conn
->force_user
&& vuser
== NULL
) {
364 DEBUG(2,("Invalid vuid used %d in accessing "
365 "share %s.\n", vuid
, lp_servicename(snum
) ));
369 return change_to_user_internal(conn
, session_info
, vuid
);
372 bool change_to_user_by_session(connection_struct
*conn
,
373 const struct auth_serversupplied_info
*session_info
)
375 SMB_ASSERT(conn
!= NULL
);
376 SMB_ASSERT(session_info
!= NULL
);
378 if ((current_user
.conn
== conn
) &&
379 (current_user
.ut
.uid
== session_info
->utok
.uid
)) {
380 DEBUG(7, ("Skipping user change - already user\n"));
385 return change_to_user_internal(conn
, session_info
, UID_FIELD_INVALID
);
388 /****************************************************************************
389 Go back to being root without changing the security context stack,
390 but modify the current_user entries.
391 ****************************************************************************/
393 bool change_to_root_user(void)
397 DEBUG(5,("change_to_root_user: now uid=(%d,%d) gid=(%d,%d)\n",
398 (int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid()));
400 current_user
.conn
= NULL
;
401 current_user
.vuid
= UID_FIELD_INVALID
;
406 /****************************************************************************
407 Become the user of an authenticated connected named pipe.
408 When this is called we are currently running as the connection
409 user. Doesn't modify current_user.
410 ****************************************************************************/
412 bool become_authenticated_pipe_user(struct pipes_struct
*p
)
417 set_sec_ctx(p
->session_info
->utok
.uid
, p
->session_info
->utok
.gid
,
418 p
->session_info
->utok
.ngroups
, p
->session_info
->utok
.groups
,
419 p
->session_info
->security_token
);
424 /****************************************************************************
425 Unbecome the user of an authenticated connected named pipe.
426 When this is called we are running as the authenticated pipe
427 user and need to go back to being the connection user. Doesn't modify
429 ****************************************************************************/
431 bool unbecome_authenticated_pipe_user(void)
433 return pop_sec_ctx();
436 /****************************************************************************
437 Utility functions used by become_xxx/unbecome_xxx.
438 ****************************************************************************/
440 static void push_conn_ctx(void)
442 struct conn_ctx
*ctx_p
;
444 /* Check we don't overflow our stack */
446 if (conn_ctx_stack_ndx
== MAX_SEC_CTX_DEPTH
) {
447 DEBUG(0, ("Connection context stack overflow!\n"));
448 smb_panic("Connection context stack overflow!\n");
451 /* Store previous user context */
452 ctx_p
= &conn_ctx_stack
[conn_ctx_stack_ndx
];
454 ctx_p
->conn
= current_user
.conn
;
455 ctx_p
->vuid
= current_user
.vuid
;
457 DEBUG(4, ("push_conn_ctx(%u) : conn_ctx_stack_ndx = %d\n",
458 (unsigned int)ctx_p
->vuid
, conn_ctx_stack_ndx
));
460 conn_ctx_stack_ndx
++;
463 static void pop_conn_ctx(void)
465 struct conn_ctx
*ctx_p
;
467 /* Check for stack underflow. */
469 if (conn_ctx_stack_ndx
== 0) {
470 DEBUG(0, ("Connection context stack underflow!\n"));
471 smb_panic("Connection context stack underflow!\n");
474 conn_ctx_stack_ndx
--;
475 ctx_p
= &conn_ctx_stack
[conn_ctx_stack_ndx
];
477 current_user
.conn
= ctx_p
->conn
;
478 current_user
.vuid
= ctx_p
->vuid
;
481 ctx_p
->vuid
= UID_FIELD_INVALID
;
484 /****************************************************************************
485 Temporarily become a root user. Must match with unbecome_root(). Saves and
486 restores the connection context.
487 ****************************************************************************/
489 void become_root(void)
492 * no good way to handle push_sec_ctx() failing without changing
493 * the prototype of become_root()
495 if (!push_sec_ctx()) {
496 smb_panic("become_root: push_sec_ctx failed");
502 /* Unbecome the root user */
504 void unbecome_root(void)
510 /****************************************************************************
511 Push the current security context then force a change via change_to_user().
512 Saves and restores the connection context.
513 ****************************************************************************/
515 bool become_user(connection_struct
*conn
, uint16 vuid
)
522 if (!change_to_user(conn
, vuid
)) {
531 bool become_user_by_session(connection_struct
*conn
,
532 const struct auth_serversupplied_info
*session_info
)
539 if (!change_to_user_by_session(conn
, session_info
)) {
548 bool unbecome_user(void)
555 /****************************************************************************
556 Return the current user we are running effectively as on this connection.
557 I'd like to make this return conn->session_info->utok.uid, but become_root()
558 doesn't alter this value.
559 ****************************************************************************/
561 uid_t
get_current_uid(connection_struct
*conn
)
563 return current_user
.ut
.uid
;
566 /****************************************************************************
567 Return the current group we are running effectively as on this connection.
568 I'd like to make this return conn->session_info->utok.gid, but become_root()
569 doesn't alter this value.
570 ****************************************************************************/
572 gid_t
get_current_gid(connection_struct
*conn
)
574 return current_user
.ut
.gid
;
577 /****************************************************************************
578 Return the UNIX token we are running effectively as on this connection.
579 I'd like to make this return &conn->session_info->utok, but become_root()
580 doesn't alter this value.
581 ****************************************************************************/
583 const struct security_unix_token
*get_current_utok(connection_struct
*conn
)
585 return ¤t_user
.ut
;
588 const struct security_token
*get_current_nttok(connection_struct
*conn
)
590 return current_user
.nt_user_token
;
593 uint16_t get_current_vuid(connection_struct
*conn
)
595 return current_user
.vuid
;