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/filesys.h"
22 #include "system/passwd.h"
23 #include "smbd/smbd.h"
24 #include "smbd/globals.h"
25 #include "../librpc/gen_ndr/netlogon.h"
26 #include "libcli/security/security.h"
27 #include "passdb/lookup_sid.h"
29 #include "../auth/auth_util.h"
30 #include "lib/util/time_basic.h"
31 #include "lib/pthreadpool/pthreadpool_tevent.h"
33 static struct smb_vfs_ev_glue *smbd_impersonate_user_ev_glue_create(
34 struct connection_struct *conn,
36 struct auth_session_info *session_info);
38 struct smbd_impersonate_debug_state {
43 static bool smbd_impersonate_debug_before_use(struct tevent_context *wrap_ev,
45 struct tevent_context *main_ev,
48 struct smbd_impersonate_debug_state *state =
49 (struct smbd_impersonate_debug_state *)private_data;
51 DEBUG(state->dbg_lvl, (
52 "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] location[%s]\n",
53 __func__, state->name, wrap_ev, state, main_ev, location));
58 static void smbd_impersonate_debug_after_use(struct tevent_context *wrap_ev,
60 struct tevent_context *main_ev,
63 struct smbd_impersonate_debug_state *state =
64 (struct smbd_impersonate_debug_state *)private_data;
66 DEBUG(state->dbg_lvl, (
67 "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] location[%s]\n",
68 __func__, state->name, wrap_ev, state, main_ev, location));
71 static void smbd_impersonate_debug_before_fd_handler(struct tevent_context *wrap_ev,
73 struct tevent_context *main_ev,
74 struct tevent_fd *fde,
76 const char *handler_name,
79 struct smbd_impersonate_debug_state *state =
80 (struct smbd_impersonate_debug_state *)private_data;
82 DEBUG(state->dbg_lvl, (
83 "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] "
84 "fde[%p] flags[0x%X] handler_name[%s] location[%s]\n",
85 __func__, state->name, wrap_ev, state, main_ev,
86 fde, flags, handler_name, location));
89 static void smbd_impersonate_debug_after_fd_handler(struct tevent_context *wrap_ev,
91 struct tevent_context *main_ev,
92 struct tevent_fd *fde,
94 const char *handler_name,
97 struct smbd_impersonate_debug_state *state =
98 (struct smbd_impersonate_debug_state *)private_data;
100 DEBUG(state->dbg_lvl, (
101 "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] "
102 "fde[%p] flags[0x%X] handler_name[%s] location[%s]\n",
103 __func__, state->name, wrap_ev, state, main_ev,
104 fde, flags, handler_name, location));
107 static void smbd_impersonate_debug_before_timer_handler(struct tevent_context *wrap_ev,
109 struct tevent_context *main_ev,
110 struct tevent_timer *te,
111 struct timeval requested_time,
112 struct timeval trigger_time,
113 const char *handler_name,
114 const char *location)
116 struct smbd_impersonate_debug_state *state =
117 (struct smbd_impersonate_debug_state *)private_data;
118 struct timeval_buf requested_buf;
119 struct timeval_buf trigger_buf;
121 DEBUG(state->dbg_lvl, (
122 "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] "
123 "te[%p] requested_time[%s] trigger_time[%s] handler_name[%s] location[%s]\n",
124 __func__, state->name, wrap_ev, state, main_ev, te,
125 timeval_str_buf(&requested_time, true, true, &requested_buf),
126 timeval_str_buf(&trigger_time, true, true, &trigger_buf),
127 handler_name, location));
130 static void smbd_impersonate_debug_after_timer_handler(struct tevent_context *wrap_ev,
132 struct tevent_context *main_ev,
133 struct tevent_timer *te,
134 struct timeval requested_time,
135 struct timeval trigger_time,
136 const char *handler_name,
137 const char *location)
139 struct smbd_impersonate_debug_state *state =
140 (struct smbd_impersonate_debug_state *)private_data;
141 struct timeval_buf requested_buf;
142 struct timeval_buf trigger_buf;
144 DEBUG(state->dbg_lvl, (
145 "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] "
146 "te[%p] requested_time[%s] trigger_time[%s] handler_name[%s] location[%s]\n",
147 __func__, state->name, wrap_ev, state, main_ev, te,
148 timeval_str_buf(&requested_time, true, true, &requested_buf),
149 timeval_str_buf(&trigger_time, true, true, &trigger_buf),
150 handler_name, location));
153 static void smbd_impersonate_debug_before_immediate_handler(struct tevent_context *wrap_ev,
155 struct tevent_context *main_ev,
156 struct tevent_immediate *im,
157 const char *handler_name,
158 const char *location)
160 struct smbd_impersonate_debug_state *state =
161 (struct smbd_impersonate_debug_state *)private_data;
163 DEBUG(state->dbg_lvl, (
164 "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] "
165 "im[%p] handler_name[%s] location[%s]\n",
166 __func__, state->name, wrap_ev, state, main_ev,
167 im, handler_name, location));
170 static void smbd_impersonate_debug_after_immediate_handler(struct tevent_context *wrap_ev,
172 struct tevent_context *main_ev,
173 struct tevent_immediate *im,
174 const char *handler_name,
175 const char *location)
177 struct smbd_impersonate_debug_state *state =
178 (struct smbd_impersonate_debug_state *)private_data;
180 DEBUG(state->dbg_lvl, (
181 "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] "
182 "im[%p] handler_name[%s] location[%s]\n",
183 __func__, state->name, wrap_ev, state, main_ev,
184 im, handler_name, location));
187 static void smbd_impersonate_debug_before_signal_handler(struct tevent_context *wrap_ev,
189 struct tevent_context *main_ev,
190 struct tevent_signal *se,
194 const char *handler_name,
195 const char *location)
197 struct smbd_impersonate_debug_state *state =
198 (struct smbd_impersonate_debug_state *)private_data;
200 DEBUG(state->dbg_lvl, (
201 "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] "
202 "se[%p] signum[%d] count[%d] siginfo[%p] handler_name[%s] location[%s]\n",
203 __func__, state->name, wrap_ev, state, main_ev,
204 se, signum, count, siginfo, handler_name, location));
207 static void smbd_impersonate_debug_after_signal_handler(struct tevent_context *wrap_ev,
209 struct tevent_context *main_ev,
210 struct tevent_signal *se,
214 const char *handler_name,
215 const char *location)
217 struct smbd_impersonate_debug_state *state =
218 (struct smbd_impersonate_debug_state *)private_data;
220 DEBUG(state->dbg_lvl, (
221 "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] "
222 "se[%p] signum[%d] count[%d] siginfo[%p] handler_name[%s] location[%s]\n",
223 __func__, state->name, wrap_ev, state, main_ev,
224 se, signum, count, siginfo, handler_name, location));
227 static const struct tevent_wrapper_ops smbd_impersonate_debug_ops = {
228 .name = "smbd_impersonate_debug",
229 .before_use = smbd_impersonate_debug_before_use,
230 .after_use = smbd_impersonate_debug_after_use,
231 .before_fd_handler = smbd_impersonate_debug_before_fd_handler,
232 .after_fd_handler = smbd_impersonate_debug_after_fd_handler,
233 .before_timer_handler = smbd_impersonate_debug_before_timer_handler,
234 .after_timer_handler = smbd_impersonate_debug_after_timer_handler,
235 .before_immediate_handler = smbd_impersonate_debug_before_immediate_handler,
236 .after_immediate_handler = smbd_impersonate_debug_after_immediate_handler,
237 .before_signal_handler = smbd_impersonate_debug_before_signal_handler,
238 .after_signal_handler = smbd_impersonate_debug_after_signal_handler,
241 struct tevent_context *_smbd_impersonate_debug_create(struct tevent_context *main_ev,
244 const char *location)
246 struct tevent_context *wrap_ev = NULL;
247 struct smbd_impersonate_debug_state *state = NULL;
249 wrap_ev = tevent_context_wrapper_create(main_ev,
251 &smbd_impersonate_debug_ops,
253 struct smbd_impersonate_debug_state);
254 if (wrap_ev == NULL) {
258 state->dbg_lvl = dbg_lvl;
259 DEBUG(state->dbg_lvl, (
260 "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] location[%s]\n",
261 __func__, state->name, wrap_ev, state, main_ev, location));
266 /* what user is current? */
267 extern struct current_user current_user;
269 /****************************************************************************
270 Become the guest user without changing the security context stack.
271 ****************************************************************************/
273 bool change_to_guest(void)
277 pass = Get_Pwnam_alloc(talloc_tos(), lp_guest_account());
283 /* MWW: From AIX FAQ patch to WU-ftpd: call initgroups before
285 initgroups(pass->pw_name, pass->pw_gid);
288 set_sec_ctx(pass->pw_uid, pass->pw_gid, 0, NULL, NULL);
290 current_user.conn = NULL;
291 current_user.vuid = UID_FIELD_INVALID;
292 current_user.need_chdir = false;
293 current_user.done_chdir = false;
300 /****************************************************************************
301 talloc free the conn->session_info if not used in the vuid cache.
302 ****************************************************************************/
304 static void free_conn_session_info_if_unused(connection_struct *conn)
308 for (i = 0; i < VUID_CACHE_SIZE; i++) {
309 struct vuid_cache_entry *ent;
310 ent = &conn->vuid_cache->array[i];
311 if (ent->vuid != UID_FIELD_INVALID &&
312 conn->session_info == ent->session_info) {
316 /* Not used, safe to free. */
317 conn->user_ev_ctx = NULL;
318 TALLOC_FREE(conn->user_vfs_evg);
319 TALLOC_FREE(conn->session_info);
322 /****************************************************************************
323 Setup the share access mask for a connection.
324 ****************************************************************************/
326 static uint32_t create_share_access_mask(int snum,
328 const struct security_token *token)
330 uint32_t share_access = 0;
332 share_access_check(token,
333 lp_const_servicename(snum),
334 MAXIMUM_ALLOWED_ACCESS,
337 if (readonly_share) {
339 ~(SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA |
340 SEC_FILE_WRITE_EA | SEC_FILE_WRITE_ATTRIBUTE |
341 SEC_DIR_DELETE_CHILD );
344 if (security_token_has_privilege(token, SEC_PRIV_SECURITY)) {
345 share_access |= SEC_FLAG_SYSTEM_SECURITY;
347 if (security_token_has_privilege(token, SEC_PRIV_RESTORE)) {
348 share_access |= SEC_RIGHTS_PRIV_RESTORE;
350 if (security_token_has_privilege(token, SEC_PRIV_BACKUP)) {
351 share_access |= SEC_RIGHTS_PRIV_BACKUP;
353 if (security_token_has_privilege(token, SEC_PRIV_TAKE_OWNERSHIP)) {
354 share_access |= SEC_STD_WRITE_OWNER;
360 /*******************************************************************
361 Calculate access mask and if this user can access this share.
362 ********************************************************************/
364 NTSTATUS check_user_share_access(connection_struct *conn,
365 const struct auth_session_info *session_info,
366 uint32_t *p_share_access,
367 bool *p_readonly_share)
369 int snum = SNUM(conn);
370 uint32_t share_access = 0;
371 bool readonly_share = false;
373 if (!user_ok_token(session_info->unix_info->unix_name,
374 session_info->info->domain_name,
375 session_info->security_token, snum)) {
376 return NT_STATUS_ACCESS_DENIED;
379 readonly_share = is_share_read_only_for_token(
380 session_info->unix_info->unix_name,
381 session_info->info->domain_name,
382 session_info->security_token,
385 share_access = create_share_access_mask(snum,
387 session_info->security_token);
389 if ((share_access & (FILE_READ_DATA|FILE_WRITE_DATA)) == 0) {
390 /* No access, read or write. */
391 DBG_NOTICE("user %s connection to %s denied due to share "
392 "security descriptor.\n",
393 session_info->unix_info->unix_name,
394 lp_const_servicename(snum));
395 return NT_STATUS_ACCESS_DENIED;
398 if (!readonly_share &&
399 !(share_access & FILE_WRITE_DATA)) {
400 /* smb.conf allows r/w, but the security descriptor denies
401 * write. Fall back to looking at readonly. */
402 readonly_share = true;
403 DBG_INFO("falling back to read-only access-evaluation due to "
404 "security descriptor\n");
407 *p_share_access = share_access;
408 *p_readonly_share = readonly_share;
413 /*******************************************************************
414 Check if a username is OK.
416 This sets up conn->session_info with a copy related to this vuser that
417 later code can then mess with.
418 ********************************************************************/
420 static bool check_user_ok(connection_struct *conn,
422 const struct auth_session_info *session_info,
426 bool readonly_share = false;
427 bool admin_user = false;
428 struct vuid_cache_entry *ent = NULL;
429 uint32_t share_access = 0;
432 for (i=0; i<VUID_CACHE_SIZE; i++) {
433 ent = &conn->vuid_cache->array[i];
434 if (ent->vuid == vuid) {
435 if (vuid == UID_FIELD_INVALID) {
437 * Slow path, we don't care
438 * about the array traversal.
442 free_conn_session_info_if_unused(conn);
443 conn->session_info = ent->session_info;
444 conn->user_vfs_evg = ent->user_vfs_evg;
445 conn->read_only = ent->read_only;
446 conn->share_access = ent->share_access;
447 conn->vuid = ent->vuid;
448 conn->user_ev_ctx = smb_vfs_ev_glue_ev_ctx(
450 SMB_ASSERT(conn->user_ev_ctx != NULL);
455 status = check_user_share_access(conn,
459 if (!NT_STATUS_IS_OK(status)) {
463 admin_user = token_contains_name_in_list(
464 session_info->unix_info->unix_name,
465 session_info->info->domain_name,
466 NULL, session_info->security_token, lp_admin_users(snum));
468 ent = &conn->vuid_cache->array[conn->vuid_cache->next_entry];
470 conn->vuid_cache->next_entry =
471 (conn->vuid_cache->next_entry + 1) % VUID_CACHE_SIZE;
473 TALLOC_FREE(ent->session_info);
476 * If force_user was set, all session_info's are based on the same
477 * username-based faked one.
480 ent->session_info = copy_session_info(
481 conn, conn->force_user ? conn->session_info : session_info);
483 if (ent->session_info == NULL) {
484 ent->vuid = UID_FIELD_INVALID;
489 DEBUG(2,("check_user_ok: user %s is an admin user. "
490 "Setting uid as %d\n",
491 ent->session_info->unix_info->unix_name,
492 sec_initial_uid() ));
493 ent->session_info->unix_token->uid = sec_initial_uid();
496 ent->user_vfs_evg = smbd_impersonate_user_ev_glue_create(conn,
497 vuid, ent->session_info);
498 if (ent->user_vfs_evg == NULL) {
499 TALLOC_FREE(ent->session_info);
500 ent->vuid = UID_FIELD_INVALID;
505 * It's actually OK to call check_user_ok() with
506 * vuid == UID_FIELD_INVALID as called from change_to_user_by_session().
507 * All this will do is throw away one entry in the cache.
511 ent->read_only = readonly_share;
512 ent->share_access = share_access;
513 free_conn_session_info_if_unused(conn);
514 conn->session_info = ent->session_info;
515 conn->vuid = ent->vuid;
516 conn->user_vfs_evg = ent->user_vfs_evg;
517 conn->user_ev_ctx = smb_vfs_ev_glue_ev_ctx(conn->user_vfs_evg);
518 SMB_ASSERT(conn->user_ev_ctx != NULL);
520 if (vuid == UID_FIELD_INVALID) {
522 * Not strictly needed, just make it really
523 * clear this entry is actually an unused one.
525 ent->read_only = false;
526 ent->share_access = 0;
527 ent->session_info = NULL;
528 ent->user_vfs_evg = NULL;
531 conn->read_only = readonly_share;
532 conn->share_access = share_access;
537 /****************************************************************************
538 Become the user of a connection number without changing the security context
539 stack, but modify the current_user entries.
540 ****************************************************************************/
542 static bool change_to_user_internal(connection_struct *conn,
543 const struct auth_session_info *session_info,
551 gid_t *group_list = NULL;
554 if ((current_user.conn == conn) &&
555 (current_user.vuid == vuid) &&
556 (current_user.need_chdir == conn->tcon_done) &&
557 (current_user.ut.uid == session_info->unix_token->uid))
559 DBG_INFO("Skipping user change - already user\n");
563 set_current_user_info(session_info->unix_info->sanitized_username,
564 session_info->unix_info->unix_name,
565 session_info->info->domain_name);
569 ok = check_user_ok(conn, vuid, session_info, snum);
571 DBG_WARNING("SMB user %s (unix user %s) "
572 "not permitted access to share %s.\n",
573 session_info->unix_info->sanitized_username,
574 session_info->unix_info->unix_name,
575 lp_const_servicename(snum));
579 uid = conn->session_info->unix_token->uid;
580 gid = conn->session_info->unix_token->gid;
581 num_groups = conn->session_info->unix_token->ngroups;
582 group_list = conn->session_info->unix_token->groups;
585 * See if we should force group for this service. If so this overrides
586 * any group set in the force user code.
588 if((group_c = *lp_force_group(talloc_tos(), snum))) {
590 SMB_ASSERT(conn->force_group_gid != (gid_t)-1);
592 if (group_c == '+') {
596 * Only force group if the user is a member of the
597 * service group. Check the group memberships for this
598 * user (we already have this) to see if we should force
601 for (i = 0; i < num_groups; i++) {
602 if (group_list[i] == conn->force_group_gid) {
603 conn->session_info->unix_token->gid =
604 conn->force_group_gid;
605 gid = conn->force_group_gid;
606 gid_to_sid(&conn->session_info->security_token
612 conn->session_info->unix_token->gid = conn->force_group_gid;
613 gid = conn->force_group_gid;
614 gid_to_sid(&conn->session_info->security_token->sids[1],
619 /*Set current_user since we will immediately also call set_sec_ctx() */
620 current_user.ut.ngroups = num_groups;
621 current_user.ut.groups = group_list;
625 current_user.ut.ngroups,
626 current_user.ut.groups,
627 conn->session_info->security_token);
629 current_user.conn = conn;
630 current_user.vuid = vuid;
631 current_user.need_chdir = conn->tcon_done;
633 if (current_user.need_chdir) {
634 ok = chdir_current_service(conn);
636 DBG_ERR("chdir_current_service() failed!\n");
639 current_user.done_chdir = true;
642 if (CHECK_DEBUGLVL(DBGLVL_INFO)) {
643 struct smb_filename *cwdfname = vfs_GetWd(talloc_tos(), conn);
644 if (cwdfname == NULL) {
647 DBG_INFO("Impersonated user: uid=(%d,%d), gid=(%d,%d), cwd=[%s]\n",
652 cwdfname->base_name);
653 TALLOC_FREE(cwdfname);
659 bool change_to_user(connection_struct *conn, uint64_t vuid)
661 struct user_struct *vuser;
662 int snum = SNUM(conn);
665 DEBUG(2,("Connection not open\n"));
669 vuser = get_valid_user_struct(conn->sconn, vuid);
671 /* Invalid vuid sent */
672 DBG_WARNING("Invalid vuid %llu used on share %s.\n",
673 (unsigned long long)vuid,
674 lp_const_servicename(snum));
678 return change_to_user_internal(conn, vuser->session_info, vuid);
681 bool change_to_user_by_fsp(struct files_struct *fsp)
683 return change_to_user(fsp->conn, fsp->vuid);
686 static bool change_to_user_by_session(connection_struct *conn,
687 const struct auth_session_info *session_info)
689 SMB_ASSERT(conn != NULL);
690 SMB_ASSERT(session_info != NULL);
692 return change_to_user_internal(conn, session_info, UID_FIELD_INVALID);
695 /****************************************************************************
696 Go back to being root without changing the security context stack,
697 but modify the current_user entries.
698 ****************************************************************************/
700 bool smbd_change_to_root_user(void)
704 DEBUG(5,("change_to_root_user: now uid=(%d,%d) gid=(%d,%d)\n",
705 (int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid()));
707 current_user.conn = NULL;
708 current_user.vuid = UID_FIELD_INVALID;
709 current_user.need_chdir = false;
710 current_user.done_chdir = false;
715 /****************************************************************************
716 Become the user of an authenticated connected named pipe.
717 When this is called we are currently running as the connection
718 user. Doesn't modify current_user.
719 ****************************************************************************/
721 bool smbd_become_authenticated_pipe_user(struct auth_session_info *session_info)
726 set_sec_ctx(session_info->unix_token->uid, session_info->unix_token->gid,
727 session_info->unix_token->ngroups, session_info->unix_token->groups,
728 session_info->security_token);
730 DEBUG(5, ("Impersonated user: uid=(%d,%d), gid=(%d,%d)\n",
739 /****************************************************************************
740 Unbecome the user of an authenticated connected named pipe.
741 When this is called we are running as the authenticated pipe
742 user and need to go back to being the connection user. Doesn't modify
744 ****************************************************************************/
746 bool smbd_unbecome_authenticated_pipe_user(void)
748 return pop_sec_ctx();
751 /****************************************************************************
752 Utility functions used by become_xxx/unbecome_xxx.
753 ****************************************************************************/
755 static void push_conn_ctx(void)
757 struct conn_ctx *ctx_p;
758 extern userdom_struct current_user_info;
760 /* Check we don't overflow our stack */
762 if (conn_ctx_stack_ndx == MAX_SEC_CTX_DEPTH) {
763 DEBUG(0, ("Connection context stack overflow!\n"));
764 smb_panic("Connection context stack overflow!\n");
767 /* Store previous user context */
768 ctx_p = &conn_ctx_stack[conn_ctx_stack_ndx];
770 ctx_p->conn = current_user.conn;
771 ctx_p->vuid = current_user.vuid;
772 ctx_p->need_chdir = current_user.need_chdir;
773 ctx_p->done_chdir = current_user.done_chdir;
774 ctx_p->user_info = current_user_info;
776 DEBUG(4, ("push_conn_ctx(%llu) : conn_ctx_stack_ndx = %d\n",
777 (unsigned long long)ctx_p->vuid, conn_ctx_stack_ndx));
779 conn_ctx_stack_ndx++;
782 static void pop_conn_ctx(void)
784 struct conn_ctx *ctx_p;
786 /* Check for stack underflow. */
788 if (conn_ctx_stack_ndx == 0) {
789 DEBUG(0, ("Connection context stack underflow!\n"));
790 smb_panic("Connection context stack underflow!\n");
793 conn_ctx_stack_ndx--;
794 ctx_p = &conn_ctx_stack[conn_ctx_stack_ndx];
796 set_current_user_info(ctx_p->user_info.smb_name,
797 ctx_p->user_info.unix_name,
798 ctx_p->user_info.domain);
801 * Check if the current context did a chdir_current_service()
802 * and restore the cwd_fname of the previous context
805 if (current_user.done_chdir && ctx_p->need_chdir) {
808 ret = vfs_ChDir(ctx_p->conn, ctx_p->conn->cwd_fname);
810 DBG_ERR("vfs_ChDir() failed!\n");
811 smb_panic("vfs_ChDir() failed!\n");
815 current_user.conn = ctx_p->conn;
816 current_user.vuid = ctx_p->vuid;
817 current_user.need_chdir = ctx_p->need_chdir;
818 current_user.done_chdir = ctx_p->done_chdir;
820 *ctx_p = (struct conn_ctx) {
821 .vuid = UID_FIELD_INVALID,
825 /****************************************************************************
826 Temporarily become a root user. Must match with unbecome_root(). Saves and
827 restores the connection context.
828 ****************************************************************************/
830 void smbd_become_root(void)
833 * no good way to handle push_sec_ctx() failing without changing
834 * the prototype of become_root()
836 if (!push_sec_ctx()) {
837 smb_panic("become_root: push_sec_ctx failed");
843 /* Unbecome the root user */
845 void smbd_unbecome_root(void)
851 bool become_guest(void)
862 ok = change_to_guest();
872 void unbecome_guest(void)
879 /****************************************************************************
880 Push the current security context then force a change via change_to_user().
881 Saves and restores the connection context.
882 ****************************************************************************/
884 bool become_user(connection_struct *conn, uint64_t vuid)
891 if (!change_to_user(conn, vuid)) {
900 bool become_user_by_fsp(struct files_struct *fsp)
902 return become_user(fsp->conn, fsp->vuid);
905 bool become_user_by_session(connection_struct *conn,
906 const struct auth_session_info *session_info)
913 if (!change_to_user_by_session(conn, session_info)) {
922 bool unbecome_user(void)
929 /****************************************************************************
930 Return the current user we are running effectively as on this connection.
931 I'd like to make this return conn->session_info->unix_token->uid, but become_root()
932 doesn't alter this value.
933 ****************************************************************************/
935 uid_t get_current_uid(connection_struct *conn)
937 return current_user.ut.uid;
940 /****************************************************************************
941 Return the current group we are running effectively as on this connection.
942 I'd like to make this return conn->session_info->unix_token->gid, but become_root()
943 doesn't alter this value.
944 ****************************************************************************/
946 gid_t get_current_gid(connection_struct *conn)
948 return current_user.ut.gid;
951 /****************************************************************************
952 Return the UNIX token we are running effectively as on this connection.
953 I'd like to make this return &conn->session_info->unix_token-> but become_root()
954 doesn't alter this value.
955 ****************************************************************************/
957 const struct security_unix_token *get_current_utok(connection_struct *conn)
959 return ¤t_user.ut;
962 /****************************************************************************
963 Return the Windows token we are running effectively as on this connection.
964 If this is currently a NULL token as we're inside become_root() - a temporary
965 UNIX security override, then we search up the stack for the previous active
967 ****************************************************************************/
969 const struct security_token *get_current_nttok(connection_struct *conn)
971 if (current_user.nt_user_token) {
972 return current_user.nt_user_token;
974 return sec_ctx_active_token();
977 uint64_t get_current_vuid(connection_struct *conn)
979 return current_user.vuid;
982 struct smbd_impersonate_conn_vuid_state {
983 struct connection_struct *conn;
987 static bool smbd_impersonate_conn_vuid_before_use(
988 struct tevent_context *wrap_ev,
990 struct tevent_context *main_ev,
991 const char *location)
993 struct smbd_impersonate_conn_vuid_state *state =
994 talloc_get_type_abort(private_data,
995 struct smbd_impersonate_conn_vuid_state);
998 DEBUG(11,("%s: wrap_ev[%p] main_ev[%p] location[%s]"
999 "old uid[%ju] old gid[%ju] vuid[%ju] cwd[%s]\n",
1000 __func__, wrap_ev, main_ev, location,
1001 (uintmax_t)geteuid(), (uintmax_t)getegid(),
1002 (uintmax_t)state->vuid, state->conn->cwd_fname->base_name));
1004 ok = become_user(state->conn, state->vuid);
1006 smb_panic("smbd_impersonate_conn_vuid_before_use() - failed");
1010 DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1011 __func__, state->conn->session_info->unix_info->unix_name,
1012 (uintmax_t)geteuid(), (uintmax_t)getegid(),
1013 state->conn->cwd_fname->base_name));
1018 static void smbd_impersonate_conn_vuid_after_use(
1019 struct tevent_context *wrap_ev,
1021 struct tevent_context *main_ev,
1022 const char *location)
1024 struct smbd_impersonate_conn_vuid_state *state =
1025 talloc_get_type_abort(private_data,
1026 struct smbd_impersonate_conn_vuid_state);
1029 DEBUG(11,("%s: deimpersonating[%s] uid[%ju] gid[%ju] cwd[%s] "
1031 __func__, state->conn->session_info->unix_info->unix_name,
1032 (uintmax_t)geteuid(), (uintmax_t)getegid(),
1033 state->conn->cwd_fname->base_name, location));
1035 ok = unbecome_user();
1037 smb_panic("smbd_impersonate_conn_vuid_after_use() - failed");
1041 DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1042 __func__, state->conn->session_info->unix_info->unix_name,
1043 (uintmax_t)geteuid(), (uintmax_t)getegid(),
1044 state->conn->cwd_fname->base_name));
1047 static void smbd_impersonate_conn_vuid_before_fd_handler(
1048 struct tevent_context *wrap_ev,
1050 struct tevent_context *main_ev,
1051 struct tevent_fd *fde,
1053 const char *handler_name,
1054 const char *location)
1056 struct smbd_impersonate_conn_vuid_state *state = talloc_get_type_abort(
1057 private_data, struct smbd_impersonate_conn_vuid_state);
1060 DEBUG(11,("%s: fde[%p] flags[%ju] handler_name[%s] location[%s]\n",
1061 __func__, fde, (uintmax_t)flags, handler_name, location));
1063 ok = change_to_user(state->conn, state->vuid);
1065 smb_panic("smbd_impersonate_conn_vuid_before_use() - failed");
1069 DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1070 __func__, state->conn->session_info->unix_info->unix_name,
1071 (uintmax_t)geteuid(), (uintmax_t)getegid(),
1072 state->conn->cwd_fname->base_name));
1075 static void smbd_impersonate_conn_vuid_after_fd_handler(
1076 struct tevent_context *wrap_ev,
1078 struct tevent_context *main_ev,
1079 struct tevent_fd *fde,
1081 const char *handler_name,
1082 const char *location)
1084 DEBUG(11,("%s: fde[%p] handler_name[%s] location[%s]\n",
1085 __func__, fde, handler_name, location));
1087 /* be lazy and defer change_to_root_user() */
1090 static void smbd_impersonate_conn_vuid_before_timer_handler(
1091 struct tevent_context *wrap_ev,
1093 struct tevent_context *main_ev,
1094 struct tevent_timer *te,
1095 struct timeval requested_time,
1096 struct timeval trigger_time,
1097 const char *handler_name,
1098 const char *location)
1100 struct smbd_impersonate_conn_vuid_state *state = talloc_get_type_abort(
1101 private_data, struct smbd_impersonate_conn_vuid_state);
1102 struct timeval_buf requested_buf;
1103 struct timeval_buf trigger_buf;
1106 DEBUG(11,("%s: te[%p] requested_time[%s] trigger_time[%s] "
1107 "handler_name[%s] location[%s]\n",
1109 timeval_str_buf(&requested_time, true, true, &requested_buf),
1110 timeval_str_buf(&trigger_time, true, true, &trigger_buf),
1111 handler_name, location));
1113 ok = change_to_user(state->conn, state->vuid);
1115 smb_panic("smbd_impersonate_conn_vuid_before_use() - failed");
1119 DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1120 __func__, state->conn->session_info->unix_info->unix_name,
1121 (uintmax_t)geteuid(), (uintmax_t)getegid(),
1122 state->conn->cwd_fname->base_name));
1125 static void smbd_impersonate_conn_vuid_after_timer_handler(
1126 struct tevent_context *wrap_ev,
1128 struct tevent_context *main_ev,
1129 struct tevent_timer *te,
1130 struct timeval requested_time,
1131 struct timeval trigger_time,
1132 const char *handler_name,
1133 const char *location)
1135 DEBUG(11,("%s: te[%p] handler_name[%s] location[%s]\n",
1136 __func__, te, handler_name, location));
1138 /* be lazy and defer change_to_root_user() */
1141 static void smbd_impersonate_conn_vuid_before_immediate_handler(
1142 struct tevent_context *wrap_ev,
1144 struct tevent_context *main_ev,
1145 struct tevent_immediate *im,
1146 const char *handler_name,
1147 const char *location)
1149 struct smbd_impersonate_conn_vuid_state *state = talloc_get_type_abort(
1150 private_data, struct smbd_impersonate_conn_vuid_state);
1153 DEBUG(11,("%s: im[%p] handler_name[%s] location[%s]\n",
1154 __func__, im, handler_name, location));
1156 ok = change_to_user(state->conn, state->vuid);
1158 smb_panic("smbd_impersonate_conn_vuid_before_use() - failed");
1162 DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1163 __func__, state->conn->session_info->unix_info->unix_name,
1164 (uintmax_t)geteuid(), (uintmax_t)getegid(),
1165 state->conn->cwd_fname->base_name));
1168 static void smbd_impersonate_conn_vuid_after_immediate_handler(
1169 struct tevent_context *wrap_ev,
1171 struct tevent_context *main_ev,
1172 struct tevent_immediate *im,
1173 const char *handler_name,
1174 const char *location)
1176 DEBUG(11,("%s: im[%p] handler_name[%s] location[%s]\n",
1177 __func__, im, handler_name, location));
1179 /* be lazy and defer unbecome_user() */
1182 static void smbd_impersonate_conn_vuid_before_signal_handler(
1183 struct tevent_context *wrap_ev,
1185 struct tevent_context *main_ev,
1186 struct tevent_signal *se,
1190 const char *handler_name,
1191 const char *location)
1193 struct smbd_impersonate_conn_vuid_state *state = talloc_get_type_abort(
1194 private_data, struct smbd_impersonate_conn_vuid_state);
1197 DEBUG(11,("%s: se[%p] signum[%d] count[%d] siginfo[%p] "
1198 "handler_name[%s] location[%s]\n",
1199 __func__, se, signum, count, siginfo, handler_name, location));
1201 ok = change_to_user(state->conn, state->vuid);
1203 smb_panic("smbd_impersonate_conn_vuid_before_use() - failed");
1207 DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1208 __func__, state->conn->session_info->unix_info->unix_name,
1209 (uintmax_t)geteuid(), (uintmax_t)getegid(),
1210 state->conn->cwd_fname->base_name));
1213 static void smbd_impersonate_conn_vuid_after_signal_handler(
1214 struct tevent_context *wrap_ev,
1216 struct tevent_context *main_ev,
1217 struct tevent_signal *se,
1221 const char *handler_name,
1222 const char *location)
1224 DEBUG(11,("%s: se[%p] handler_name[%s] location[%s]\n",
1225 __func__, se, handler_name, location));
1227 /* be lazy and defer change_to_root_user() */
1230 static const struct tevent_wrapper_ops smbd_impersonate_conn_vuid_ops = {
1231 .name = "smbd_impersonate_conn_vuid",
1232 .before_use = smbd_impersonate_conn_vuid_before_use,
1233 .after_use = smbd_impersonate_conn_vuid_after_use,
1234 .before_fd_handler = smbd_impersonate_conn_vuid_before_fd_handler,
1235 .after_fd_handler = smbd_impersonate_conn_vuid_after_fd_handler,
1236 .before_timer_handler = smbd_impersonate_conn_vuid_before_timer_handler,
1237 .after_timer_handler = smbd_impersonate_conn_vuid_after_timer_handler,
1238 .before_immediate_handler = smbd_impersonate_conn_vuid_before_immediate_handler,
1239 .after_immediate_handler = smbd_impersonate_conn_vuid_after_immediate_handler,
1240 .before_signal_handler = smbd_impersonate_conn_vuid_before_signal_handler,
1241 .after_signal_handler = smbd_impersonate_conn_vuid_after_signal_handler,
1244 struct tevent_context *smbd_impersonate_conn_vuid_create(
1245 struct tevent_context *main_ev,
1246 struct connection_struct *conn,
1249 struct tevent_context *ev = NULL;
1250 struct smbd_impersonate_conn_vuid_state *state = NULL;
1252 ev = tevent_context_wrapper_create(main_ev,
1254 &smbd_impersonate_conn_vuid_ops,
1256 struct smbd_impersonate_conn_vuid_state);
1266 struct smbd_impersonate_conn_sess_state {
1267 struct connection_struct *conn;
1268 struct auth_session_info *session_info;
1271 static bool smbd_impersonate_conn_sess_before_use(struct tevent_context *wrap_ev,
1273 struct tevent_context *main_ev,
1274 const char *location)
1276 struct smbd_impersonate_conn_sess_state *state = talloc_get_type_abort(
1277 private_data, struct smbd_impersonate_conn_sess_state);
1280 DEBUG(11,("%s: impersonating user[%s] wrap_ev[%p] main_ev[%p] "
1281 "location[%s] old uid[%ju] old gid[%ju] cwd[%s]\n",
1282 __func__, state->session_info->unix_info->unix_name,
1283 wrap_ev, main_ev, location,
1284 (uintmax_t)geteuid(), (uintmax_t)getegid(),
1285 state->conn->cwd_fname->base_name));
1287 ok = become_user_by_session(state->conn, state->session_info);
1292 DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1293 __func__, state->conn->session_info->unix_info->unix_name,
1294 (uintmax_t)geteuid(), (uintmax_t)getegid(),
1295 state->conn->cwd_fname->base_name));
1300 static void smbd_impersonate_conn_sess_after_use(struct tevent_context *wrap_ev,
1302 struct tevent_context *main_ev,
1303 const char *location)
1305 struct smbd_impersonate_conn_sess_state *state = talloc_get_type_abort(
1306 private_data, struct smbd_impersonate_conn_sess_state);
1309 DEBUG(11,("%s: deimpersonating[%s] uid[%ju] gid[%ju] cwd[%s] "
1311 __func__, state->session_info->unix_info->unix_name,
1312 (uintmax_t)geteuid(), (uintmax_t)getegid(),
1313 state->conn->cwd_fname->base_name, location));
1315 ok = unbecome_user();
1317 smb_panic("smbd_impersonate_conn_sess_after_use() - failed");
1321 DEBUG(11,("%s: deimpersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1322 __func__, state->conn->session_info->unix_info->unix_name,
1323 (uintmax_t)geteuid(), (uintmax_t)getegid(),
1324 state->conn->cwd_fname->base_name));
1327 static void smbd_impersonate_conn_sess_before_fd_handler(
1328 struct tevent_context *wrap_ev,
1330 struct tevent_context *main_ev,
1331 struct tevent_fd *fde,
1333 const char *handler_name,
1334 const char *location)
1336 struct smbd_impersonate_conn_sess_state *state = talloc_get_type_abort(
1337 private_data, struct smbd_impersonate_conn_sess_state);
1340 DEBUG(11,("%s: fde[%p] flags[%ju] handler_name[%s] location[%s]\n",
1341 __func__, fde, (uintmax_t)flags, handler_name, location));
1343 ok = change_to_user_by_session(state->conn, state->session_info);
1345 smb_panic("smbd_impersonate_conn_sess_before_fd_handler failed");
1349 DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1350 __func__, state->conn->session_info->unix_info->unix_name,
1351 (uintmax_t)geteuid(), (uintmax_t)getegid(),
1352 state->conn->cwd_fname->base_name));
1355 static void smbd_impersonate_conn_sess_after_fd_handler(struct tevent_context *wrap_ev,
1357 struct tevent_context *main_ev,
1358 struct tevent_fd *fde,
1360 const char *handler_name,
1361 const char *location)
1363 DEBUG(11,("%s: fde[%p] handler_name[%s] location[%s]\n",
1364 __func__, fde, handler_name, location));
1366 /* be lazy and defer change_to_root_user() */
1369 static void smbd_impersonate_conn_sess_before_timer_handler(
1370 struct tevent_context *wrap_ev,
1372 struct tevent_context *main_ev,
1373 struct tevent_timer *te,
1374 struct timeval requested_time,
1375 struct timeval trigger_time,
1376 const char *handler_name,
1377 const char *location)
1379 struct smbd_impersonate_conn_sess_state *state = talloc_get_type_abort(
1380 private_data, struct smbd_impersonate_conn_sess_state);
1381 struct timeval_buf requested_buf;
1382 struct timeval_buf trigger_buf;
1385 DEBUG(11,("%s: te[%p] requested_time[%s] trigger_time[%s] "
1386 "handler_name[%s] location[%s]\n",
1388 timeval_str_buf(&requested_time, true, true, &requested_buf),
1389 timeval_str_buf(&trigger_time, true, true, &trigger_buf),
1390 handler_name, location));
1392 ok = change_to_user_by_session(state->conn, state->session_info);
1394 smb_panic("smbd_impersonate_conn_sess_before_tm_handler failed");
1398 DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1399 __func__, state->conn->session_info->unix_info->unix_name,
1400 (uintmax_t)geteuid(), (uintmax_t)getegid(),
1401 state->conn->cwd_fname->base_name));
1404 static void smbd_impersonate_conn_sess_after_timer_handler(
1405 struct tevent_context *wrap_ev,
1407 struct tevent_context *main_ev,
1408 struct tevent_timer *te,
1409 struct timeval requested_time,
1410 struct timeval trigger_time,
1411 const char *handler_name,
1412 const char *location)
1414 DEBUG(11,("%s: te[%p] handler_name[%s] location[%s]\n",
1415 __func__, te, handler_name, location));
1417 /* be lazy and defer change_to_root_user() */
1420 static void smbd_impersonate_conn_sess_before_immediate_handler(
1421 struct tevent_context *wrap_ev,
1423 struct tevent_context *main_ev,
1424 struct tevent_immediate *im,
1425 const char *handler_name,
1426 const char *location)
1428 struct smbd_impersonate_conn_sess_state *state = talloc_get_type_abort(
1429 private_data, struct smbd_impersonate_conn_sess_state);
1432 DEBUG(11,("%s: im[%p] handler_name[%s] location[%s]\n",
1433 __func__, im, handler_name, location));
1435 ok = change_to_user_by_session(state->conn, state->session_info);
1437 smb_panic("smbd_impersonate_conn_sess_before_im_handler failed");
1441 DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1442 __func__, state->conn->session_info->unix_info->unix_name,
1443 (uintmax_t)geteuid(), (uintmax_t)getegid(),
1444 state->conn->cwd_fname->base_name));
1447 static void smbd_impersonate_conn_sess_after_immediate_handler(
1448 struct tevent_context *wrap_ev,
1450 struct tevent_context *main_ev,
1451 struct tevent_immediate *im,
1452 const char *handler_name,
1453 const char *location)
1455 DEBUG(11,("%s: im[%p] handler_name[%s] location[%s]\n",
1456 __func__, im, handler_name, location));
1458 /* be lazy and defer unbecome_user() */
1461 static void smbd_impersonate_conn_sess_before_signal_handler(
1462 struct tevent_context *wrap_ev,
1464 struct tevent_context *main_ev,
1465 struct tevent_signal *se,
1469 const char *handler_name,
1470 const char *location)
1472 struct smbd_impersonate_conn_sess_state *state = talloc_get_type_abort(
1473 private_data, struct smbd_impersonate_conn_sess_state);
1476 DEBUG(11,("%s: se[%p] signum[%d] count[%d] siginfo[%p] "
1477 "handler_name[%s] location[%s]\n",
1478 __func__, se, signum, count, siginfo, handler_name, location));
1480 ok = change_to_user_by_session(state->conn, state->session_info);
1482 smb_panic("smbd_impersonate_conn_sess_before_si_handler failed");
1486 DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1487 __func__, state->conn->session_info->unix_info->unix_name,
1488 (uintmax_t)geteuid(), (uintmax_t)getegid(),
1489 state->conn->cwd_fname->base_name));
1492 static void smbd_impersonate_conn_sess_after_signal_handler(
1493 struct tevent_context *wrap_ev,
1495 struct tevent_context *main_ev,
1496 struct tevent_signal *se,
1500 const char *handler_name,
1501 const char *location)
1503 DEBUG(11,("%s: se[%p] handler_name[%s] location[%s]\n",
1504 __func__, se, handler_name, location));
1506 /* be lazy and defer change_to_root_user() */
1509 static const struct tevent_wrapper_ops smbd_impersonate_conn_sess_ops = {
1510 .name = "smbd_impersonate_conn_sess",
1511 .before_use = smbd_impersonate_conn_sess_before_use,
1512 .after_use = smbd_impersonate_conn_sess_after_use,
1513 .before_fd_handler = smbd_impersonate_conn_sess_before_fd_handler,
1514 .after_fd_handler = smbd_impersonate_conn_sess_after_fd_handler,
1515 .before_timer_handler = smbd_impersonate_conn_sess_before_timer_handler,
1516 .after_timer_handler = smbd_impersonate_conn_sess_after_timer_handler,
1517 .before_immediate_handler = smbd_impersonate_conn_sess_before_immediate_handler,
1518 .after_immediate_handler = smbd_impersonate_conn_sess_after_immediate_handler,
1519 .before_signal_handler = smbd_impersonate_conn_sess_before_signal_handler,
1520 .after_signal_handler = smbd_impersonate_conn_sess_after_signal_handler,
1523 struct tevent_context *smbd_impersonate_conn_sess_create(
1524 struct tevent_context *main_ev,
1525 struct connection_struct *conn,
1526 struct auth_session_info *session_info)
1528 struct tevent_context *ev = NULL;
1529 struct smbd_impersonate_conn_sess_state *state = NULL;
1531 ev = tevent_context_wrapper_create(main_ev,
1533 &smbd_impersonate_conn_sess_ops,
1535 struct smbd_impersonate_conn_sess_state);
1540 state->session_info = session_info;
1545 struct smbd_impersonate_root_state {
1549 static bool smbd_impersonate_root_before_use(struct tevent_context *wrap_ev,
1551 struct tevent_context *main_ev,
1552 const char *location)
1554 DEBUG(11,("%s: wrap_ev[%p] main_ev[%p] location[%s]"
1555 "uid[%ju] gid[%ju]\n",
1556 __func__, wrap_ev, main_ev, location,
1557 (uintmax_t)geteuid(), (uintmax_t)getegid()));
1563 static void smbd_impersonate_root_after_use(struct tevent_context *wrap_ev,
1565 struct tevent_context *main_ev,
1566 const char *location)
1570 DEBUG(11,("%s: uid[%ju] gid[%ju] location[%s]\n",
1571 __func__, (uintmax_t)geteuid(), (uintmax_t)getegid(),
1575 static void smbd_impersonate_root_before_fd_handler(struct tevent_context *wrap_ev,
1577 struct tevent_context *main_ev,
1578 struct tevent_fd *fde,
1580 const char *handler_name,
1581 const char *location)
1583 DEBUG(11,("%s: fde[%p] flags[%ju] handler_name[%s] location[%s]\n",
1584 __func__, fde, (uintmax_t)flags, handler_name, location));
1586 smbd_impersonate_root_before_use(wrap_ev, private_data, main_ev, location);
1589 static void smbd_impersonate_root_after_fd_handler(struct tevent_context *wrap_ev,
1591 struct tevent_context *main_ev,
1592 struct tevent_fd *fde,
1594 const char *handler_name,
1595 const char *location)
1597 DEBUG(11,("%s: fde[%p] handler_name[%s] location[%s]\n",
1598 __func__, fde, handler_name, location));
1600 smbd_impersonate_root_after_use(wrap_ev, private_data, main_ev, location);
1603 static void smbd_impersonate_root_before_timer_handler(struct tevent_context *wrap_ev,
1605 struct tevent_context *main_ev,
1606 struct tevent_timer *te,
1607 struct timeval requested_time,
1608 struct timeval trigger_time,
1609 const char *handler_name,
1610 const char *location)
1612 struct timeval_buf requested_buf;
1613 struct timeval_buf trigger_buf;
1615 DEBUG(11,("%s: te[%p] requested_time[%s] trigger_time[%s] "
1616 "handler_name[%s] location[%s]\n",
1618 timeval_str_buf(&requested_time, true, true, &requested_buf),
1619 timeval_str_buf(&trigger_time, true, true, &trigger_buf),
1620 handler_name, location));
1622 smbd_impersonate_root_before_use(wrap_ev, private_data, main_ev, location);
1625 static void smbd_impersonate_root_after_timer_handler(struct tevent_context *wrap_ev,
1627 struct tevent_context *main_ev,
1628 struct tevent_timer *te,
1629 struct timeval requested_time,
1630 struct timeval trigger_time,
1631 const char *handler_name,
1632 const char *location)
1634 DEBUG(11,("%s: te[%p] handler_name[%s] location[%s]\n",
1635 __func__, te, handler_name, location));
1637 smbd_impersonate_root_after_use(wrap_ev, private_data, main_ev, location);
1640 static void smbd_impersonate_root_before_immediate_handler(struct tevent_context *wrap_ev,
1642 struct tevent_context *main_ev,
1643 struct tevent_immediate *im,
1644 const char *handler_name,
1645 const char *location)
1647 DEBUG(11,("%s: im[%p] handler_name[%s] location[%s]\n",
1648 __func__, im, handler_name, location));
1650 smbd_impersonate_root_before_use(wrap_ev, private_data, main_ev, location);
1653 static void smbd_impersonate_root_after_immediate_handler(struct tevent_context *wrap_ev,
1655 struct tevent_context *main_ev,
1656 struct tevent_immediate *im,
1657 const char *handler_name,
1658 const char *location)
1660 DEBUG(11,("%s: im[%p] handler_name[%s] location[%s]\n",
1661 __func__, im, handler_name, location));
1663 smbd_impersonate_root_after_use(wrap_ev, private_data, main_ev, location);
1666 static void smbd_impersonate_root_before_signal_handler(struct tevent_context *wrap_ev,
1668 struct tevent_context *main_ev,
1669 struct tevent_signal *se,
1673 const char *handler_name,
1674 const char *location)
1676 DEBUG(11,("%s: se[%p] signum[%d] count[%d] siginfo[%p] "
1677 "handler_name[%s] location[%s]\n",
1678 __func__, se, signum, count, siginfo, handler_name, location));
1680 smbd_impersonate_root_before_use(wrap_ev, private_data, main_ev, location);
1683 static void smbd_impersonate_root_after_signal_handler(struct tevent_context *wrap_ev,
1685 struct tevent_context *main_ev,
1686 struct tevent_signal *se,
1690 const char *handler_name,
1691 const char *location)
1693 DEBUG(11,("%s: se[%p] handler_name[%s] location[%s]\n",
1694 __func__, se, handler_name, location));
1696 smbd_impersonate_root_after_use(wrap_ev, private_data, main_ev, location);
1699 static const struct tevent_wrapper_ops smbd_impersonate_root_ops = {
1700 .name = "smbd_impersonate_root",
1701 .before_use = smbd_impersonate_root_before_use,
1702 .after_use = smbd_impersonate_root_after_use,
1703 .before_fd_handler = smbd_impersonate_root_before_fd_handler,
1704 .after_fd_handler = smbd_impersonate_root_after_fd_handler,
1705 .before_timer_handler = smbd_impersonate_root_before_timer_handler,
1706 .after_timer_handler = smbd_impersonate_root_after_timer_handler,
1707 .before_immediate_handler = smbd_impersonate_root_before_immediate_handler,
1708 .after_immediate_handler = smbd_impersonate_root_after_immediate_handler,
1709 .before_signal_handler = smbd_impersonate_root_before_signal_handler,
1710 .after_signal_handler = smbd_impersonate_root_after_signal_handler,
1713 struct tevent_context *smbd_impersonate_root_create(struct tevent_context *main_ev)
1715 struct tevent_context *ev = NULL;
1716 struct smbd_impersonate_root_state *state = NULL;
1718 ev = tevent_context_wrapper_create(main_ev,
1720 &smbd_impersonate_root_ops,
1722 struct smbd_impersonate_root_state);
1730 struct smbd_impersonate_guest_state {
1734 static bool smbd_impersonate_guest_before_use(struct tevent_context *wrap_ev,
1736 struct tevent_context *main_ev,
1737 const char *location)
1739 DEBUG(11,("%s: wrap_ev[%p] main_ev[%p] location[%s]"
1740 "uid[%ju] gid[%ju]\n",
1741 __func__, wrap_ev, main_ev, location,
1742 (uintmax_t)geteuid(), (uintmax_t)getegid()));
1744 return become_guest();
1747 static void smbd_impersonate_guest_after_use(struct tevent_context *wrap_ev,
1749 struct tevent_context *main_ev,
1750 const char *location)
1754 DEBUG(11,("%s: uid[%ju] gid[%ju] location[%s]\n",
1755 __func__, (uintmax_t)geteuid(), (uintmax_t)getegid(),
1759 static void smbd_impersonate_guest_before_fd_handler(struct tevent_context *wrap_ev,
1761 struct tevent_context *main_ev,
1762 struct tevent_fd *fde,
1764 const char *handler_name,
1765 const char *location)
1769 DEBUG(11,("%s: fde[%p] flags[%ju] handler_name[%s] location[%s]\n",
1770 __func__, fde, (uintmax_t)flags, handler_name, location));
1772 ok = smbd_impersonate_guest_before_use(wrap_ev, private_data,
1775 smb_panic("smbd_impersonate_guest_before_use() - failed");
1780 static void smbd_impersonate_guest_after_fd_handler(struct tevent_context *wrap_ev,
1782 struct tevent_context *main_ev,
1783 struct tevent_fd *fde,
1785 const char *handler_name,
1786 const char *location)
1788 DEBUG(11,("%s: fde[%p] handler_name[%s] location[%s]\n",
1789 __func__, fde, handler_name, location));
1791 smbd_impersonate_guest_after_use(wrap_ev, private_data, main_ev, location);
1794 static void smbd_impersonate_guest_before_timer_handler(struct tevent_context *wrap_ev,
1796 struct tevent_context *main_ev,
1797 struct tevent_timer *te,
1798 struct timeval requested_time,
1799 struct timeval trigger_time,
1800 const char *handler_name,
1801 const char *location)
1804 struct timeval_buf requested_buf;
1805 struct timeval_buf trigger_buf;
1807 DEBUG(11,("%s: te[%p] requested_time[%s] trigger_time[%s] "
1808 "handler_name[%s] location[%s]\n",
1810 timeval_str_buf(&requested_time, true, true, &requested_buf),
1811 timeval_str_buf(&trigger_time, true, true, &trigger_buf),
1812 handler_name, location));
1814 ok = smbd_impersonate_guest_before_use(wrap_ev, private_data,
1817 smb_panic("smbd_impersonate_guest_before_use() - failed");
1822 static void smbd_impersonate_guest_after_timer_handler(struct tevent_context *wrap_ev,
1824 struct tevent_context *main_ev,
1825 struct tevent_timer *te,
1826 struct timeval requested_time,
1827 struct timeval trigger_time,
1828 const char *handler_name,
1829 const char *location)
1831 DEBUG(11,("%s: te[%p] handler_name[%s] location[%s]\n",
1832 __func__, te, handler_name, location));
1834 smbd_impersonate_guest_after_use(wrap_ev, private_data, main_ev, location);
1837 static void smbd_impersonate_guest_before_immediate_handler(struct tevent_context *wrap_ev,
1839 struct tevent_context *main_ev,
1840 struct tevent_immediate *im,
1841 const char *handler_name,
1842 const char *location)
1846 DEBUG(11,("%s: im[%p] handler_name[%s] location[%s]\n",
1847 __func__, im, handler_name, location));
1849 ok = smbd_impersonate_guest_before_use(wrap_ev, private_data,
1852 smb_panic("smbd_impersonate_guest_before_use() - failed");
1857 static void smbd_impersonate_guest_after_immediate_handler(struct tevent_context *wrap_ev,
1859 struct tevent_context *main_ev,
1860 struct tevent_immediate *im,
1861 const char *handler_name,
1862 const char *location)
1864 DEBUG(11,("%s: im[%p] handler_name[%s] location[%s]\n",
1865 __func__, im, handler_name, location));
1867 smbd_impersonate_guest_after_use(wrap_ev, private_data, main_ev, location);
1870 static void smbd_impersonate_guest_before_signal_handler(struct tevent_context *wrap_ev,
1872 struct tevent_context *main_ev,
1873 struct tevent_signal *se,
1877 const char *handler_name,
1878 const char *location)
1882 DEBUG(11,("%s: se[%p] signum[%d] count[%d] siginfo[%p] "
1883 "handler_name[%s] location[%s]\n",
1884 __func__, se, signum, count, siginfo, handler_name, location));
1886 ok = smbd_impersonate_guest_before_use(wrap_ev, private_data,
1889 smb_panic("smbd_impersonate_guest_before_use() - failed");
1894 static void smbd_impersonate_guest_after_signal_handler(struct tevent_context *wrap_ev,
1896 struct tevent_context *main_ev,
1897 struct tevent_signal *se,
1901 const char *handler_name,
1902 const char *location)
1904 DEBUG(11,("%s: se[%p] handler_name[%s] location[%s]\n",
1905 __func__, se, handler_name, location));
1907 smbd_impersonate_guest_after_use(wrap_ev, private_data, main_ev, location);
1910 static const struct tevent_wrapper_ops smbd_impersonate_guest_ops = {
1911 .name = "smbd_impersonate_guest",
1912 .before_use = smbd_impersonate_guest_before_use,
1913 .after_use = smbd_impersonate_guest_after_use,
1914 .before_fd_handler = smbd_impersonate_guest_before_fd_handler,
1915 .after_fd_handler = smbd_impersonate_guest_after_fd_handler,
1916 .before_timer_handler = smbd_impersonate_guest_before_timer_handler,
1917 .after_timer_handler = smbd_impersonate_guest_after_timer_handler,
1918 .before_immediate_handler = smbd_impersonate_guest_before_immediate_handler,
1919 .after_immediate_handler = smbd_impersonate_guest_after_immediate_handler,
1920 .before_signal_handler = smbd_impersonate_guest_before_signal_handler,
1921 .after_signal_handler = smbd_impersonate_guest_after_signal_handler,
1924 struct tevent_context *smbd_impersonate_guest_create(struct tevent_context *main_ev)
1926 struct tevent_context *ev = NULL;
1927 struct smbd_impersonate_guest_state *state = NULL;
1929 ev = tevent_context_wrapper_create(main_ev,
1931 &smbd_impersonate_guest_ops,
1933 struct smbd_impersonate_guest_state);
1941 struct smbd_impersonate_tp_current_state {
1942 const void *conn_ptr;
1943 uint64_t vuid; /* SMB2 compat */
1944 struct security_unix_token partial_ut;
1949 static int smbd_impersonate_tp_current_state_destructor(
1950 struct smbd_impersonate_tp_current_state *state)
1952 if (state->saved_cwd_fd != -1) {
1953 smb_panic(__location__);
1959 static bool smbd_impersonate_tp_current_before_job(struct pthreadpool_tevent *wrap,
1961 struct pthreadpool_tevent *main,
1962 const char *location)
1964 struct smbd_impersonate_tp_current_state *state =
1965 talloc_get_type_abort(private_data,
1966 struct smbd_impersonate_tp_current_state);
1968 if (state->conn_ptr != current_user.conn) {
1969 smb_panic(__location__);
1972 if (state->vuid != current_user.vuid) {
1973 smb_panic(__location__);
1976 if (state->partial_ut.uid != current_user.ut.uid) {
1977 smb_panic(__location__);
1980 if (state->partial_ut.gid != current_user.ut.gid) {
1981 smb_panic(__location__);
1984 if (state->partial_ut.ngroups != current_user.ut.ngroups) {
1985 smb_panic(__location__);
1989 * We don't verify the group list, we should have hit
1990 * an assert before. We only want to catch programmer
1993 * We just have a sync pool and want to make sure
1994 * we're already in the correct state.
1996 * So we don't do any active impersonation.
2000 * we may need to remember the current working directory
2001 * and later restore it in the after_job hook.
2003 if (state->chdir_safe) {
2004 int open_flags = O_RDONLY;
2008 open_flags |= O_DIRECTORY;
2011 open_flags |= O_CLOEXEC;
2014 state->saved_cwd_fd = open(".", open_flags);
2015 if (state->saved_cwd_fd == -1) {
2016 DBG_ERR("unable to open '.' with open_flags[0x%x] - %s\n",
2017 open_flags, strerror(errno));
2018 smb_panic("smbd_impersonate_tp_current_before_job: "
2019 "unable to open cwd '.'");
2022 ok = smb_set_close_on_exec(state->saved_cwd_fd);
2029 static bool smbd_impersonate_tp_current_after_job(struct pthreadpool_tevent *wrap,
2031 struct pthreadpool_tevent *main,
2032 const char *location)
2034 struct smbd_impersonate_tp_current_state *state =
2035 talloc_get_type_abort(private_data,
2036 struct smbd_impersonate_tp_current_state);
2040 * There's no impersonation to revert.
2042 * But we may need to reset the current working directory.
2044 if (state->saved_cwd_fd == -1) {
2048 ret = fchdir(state->saved_cwd_fd);
2050 DBG_ERR("unable to fchdir to the original directory - %s\n",
2052 smb_panic("smbd_impersonate_tp_current_after_job: "
2053 "unable restore cwd with fchdir.");
2057 close(state->saved_cwd_fd);
2058 state->saved_cwd_fd = -1;
2063 static const struct pthreadpool_tevent_wrapper_ops smbd_impersonate_tp_current_ops = {
2064 .name = "smbd_impersonate_tp_current",
2065 .before_job = smbd_impersonate_tp_current_before_job,
2066 .after_job = smbd_impersonate_tp_current_after_job,
2069 struct pthreadpool_tevent *smbd_impersonate_tp_current_create(
2070 TALLOC_CTX *mem_ctx,
2071 struct pthreadpool_tevent *sync_tp,
2072 struct connection_struct *conn,
2073 uint64_t vuid, bool chdir_safe,
2074 const struct security_unix_token *unix_token)
2076 struct pthreadpool_tevent *wrap_tp = NULL;
2077 struct smbd_impersonate_tp_current_state *state = NULL;
2080 max_threads = pthreadpool_tevent_max_threads(sync_tp);
2081 SMB_ASSERT(max_threads == 0);
2084 * We have a fake threadpool without real threads.
2085 * So we just provide a a wrapper that asserts that
2086 * we are already in the required impersonation state.
2089 wrap_tp = pthreadpool_tevent_wrapper_create(sync_tp,
2091 &smbd_impersonate_tp_current_ops,
2093 struct smbd_impersonate_tp_current_state);
2094 if (wrap_tp == NULL) {
2098 state->conn_ptr = conn;
2100 state->partial_ut = *unix_token;
2101 state->partial_ut.groups = NULL;
2102 state->chdir_safe = chdir_safe;
2103 state->saved_cwd_fd = -1;
2106 pthreadpool_tevent_force_per_thread_cwd(wrap_tp, state);
2109 talloc_set_destructor(state, smbd_impersonate_tp_current_state_destructor);
2114 struct smbd_impersonate_tp_sess_state {
2115 const struct security_unix_token *unix_token;
2118 static bool smbd_impersonate_tp_sess_before_job(struct pthreadpool_tevent *wrap,
2120 struct pthreadpool_tevent *main,
2121 const char *location)
2123 struct smbd_impersonate_tp_sess_state *state =
2124 talloc_get_type_abort(private_data,
2125 struct smbd_impersonate_tp_sess_state);
2128 /* Become the correct credential on this thread. */
2129 ret = set_thread_credentials(state->unix_token->uid,
2130 state->unix_token->gid,
2131 (size_t)state->unix_token->ngroups,
2132 state->unix_token->groups);
2140 static bool smbd_impersonate_tp_sess_after_job(struct pthreadpool_tevent *wrap,
2142 struct pthreadpool_tevent *main,
2143 const char *location)
2146 * We skip the 'unbecome' here, if the following
2147 * job cares, it already called set_thread_credentials() again.
2149 * fd based jobs on the raw pool, don't really care...
2154 static const struct pthreadpool_tevent_wrapper_ops smbd_impersonate_tp_sess_ops = {
2155 .name = "smbd_impersonate_tp_sess",
2156 .before_job = smbd_impersonate_tp_sess_before_job,
2157 .after_job = smbd_impersonate_tp_sess_after_job,
2160 static struct pthreadpool_tevent *smbd_impersonate_tp_sess_create(
2161 TALLOC_CTX *mem_ctx,
2162 struct pthreadpool_tevent *main_tp,
2163 struct auth_session_info *session_info)
2165 struct pthreadpool_tevent *wrap_tp = NULL;
2166 struct smbd_impersonate_tp_sess_state *state = NULL;
2169 max_threads = pthreadpool_tevent_max_threads(main_tp);
2170 SMB_ASSERT(max_threads > 0);
2172 wrap_tp = pthreadpool_tevent_wrapper_create(main_tp,
2174 &smbd_impersonate_tp_sess_ops,
2176 struct smbd_impersonate_tp_sess_state);
2177 if (wrap_tp == NULL) {
2181 state->unix_token = copy_unix_token(state, session_info->unix_token);
2182 if (state->unix_token == NULL) {
2183 int saved_errno = errno;
2184 TALLOC_FREE(wrap_tp);
2185 errno = saved_errno;
2192 struct smbd_impersonate_tp_become_state {
2193 void (*become_fn)(void);
2194 void (*unbecome_fn)(void);
2199 static int smbd_impersonate_tp_become_state_destructor(
2200 struct smbd_impersonate_tp_become_state *state)
2202 if (state->saved_cwd_fd != -1) {
2203 smb_panic(__location__);
2210 static bool smbd_impersonate_tp_become_before_job(struct pthreadpool_tevent *wrap,
2212 struct pthreadpool_tevent *main,
2213 const char *location)
2215 struct smbd_impersonate_tp_become_state *state =
2216 talloc_get_type_abort(private_data,
2217 struct smbd_impersonate_tp_become_state);
2220 * we may need to remember the current working directory
2221 * and later restore it in the after_job hook.
2223 if (state->chdir_safe) {
2224 int open_flags = O_RDONLY;
2228 open_flags |= O_DIRECTORY;
2231 open_flags |= O_CLOEXEC;
2234 state->saved_cwd_fd = open(".", open_flags);
2235 if (state->saved_cwd_fd == -1) {
2236 DBG_ERR("unable to open '.' with open_flags[0x%x] - %s\n",
2237 open_flags, strerror(errno));
2238 smb_panic("smbd_impersonate_tp_current_before_job: "
2239 "unable to open cwd '.'");
2242 ok = smb_set_close_on_exec(state->saved_cwd_fd);
2247 * The function should abort on error...
2254 static bool smbd_impersonate_tp_become_after_job(struct pthreadpool_tevent *wrap,
2256 struct pthreadpool_tevent *main,
2257 const char *location)
2259 struct smbd_impersonate_tp_become_state *state =
2260 talloc_get_type_abort(private_data,
2261 struct smbd_impersonate_tp_become_state);
2265 * The function should abort on error...
2267 state->unbecome_fn();
2270 * There's no impersonation to revert.
2272 * But we may need to reset the current working directory.
2274 if (state->saved_cwd_fd == -1) {
2278 ret = fchdir(state->saved_cwd_fd);
2280 DBG_ERR("unable to fchdir to the original directory - %s\n",
2282 smb_panic("smbd_impersonate_tp_current_after_job: "
2283 "unable restore cwd with fchdir.");
2287 close(state->saved_cwd_fd);
2288 state->saved_cwd_fd = -1;
2293 static const struct pthreadpool_tevent_wrapper_ops smbd_impersonate_tp_become_ops = {
2294 .name = "smbd_impersonate_tp_become",
2295 .before_job = smbd_impersonate_tp_become_before_job,
2296 .after_job = smbd_impersonate_tp_become_after_job,
2299 struct pthreadpool_tevent *smbd_impersonate_tp_become_create(
2300 TALLOC_CTX *mem_ctx,
2301 struct pthreadpool_tevent *sync_tp,
2303 void (*become_fn)(void),
2304 void (*unbecome_fn)(void))
2306 struct pthreadpool_tevent *wrap_tp = NULL;
2307 struct smbd_impersonate_tp_become_state *state = NULL;
2310 max_threads = pthreadpool_tevent_max_threads(sync_tp);
2311 SMB_ASSERT(max_threads == 0);
2314 * We have a fake threadpool without real threads.
2315 * So we just provide a a wrapper that asserts that
2316 * we are already in the required impersonation state.
2319 wrap_tp = pthreadpool_tevent_wrapper_create(sync_tp,
2321 &smbd_impersonate_tp_become_ops,
2323 struct smbd_impersonate_tp_become_state);
2324 if (wrap_tp == NULL) {
2328 state->become_fn = become_fn;
2329 state->unbecome_fn = unbecome_fn;
2330 state->chdir_safe = chdir_safe;
2331 state->saved_cwd_fd = -1;
2334 pthreadpool_tevent_force_per_thread_cwd(wrap_tp, state);
2337 talloc_set_destructor(state, smbd_impersonate_tp_become_state_destructor);
2342 struct smbd_impersonate_tp_root_state {
2343 const struct security_unix_token *fallback_token;
2346 static bool smbd_impersonate_tp_root_before_job(struct pthreadpool_tevent *wrap,
2348 struct pthreadpool_tevent *main,
2349 const char *location)
2354 * Become root in this thread.
2356 ret = set_thread_credentials(0, 0, 0, NULL);
2364 static bool smbd_impersonate_tp_root_after_job(struct pthreadpool_tevent *wrap,
2366 struct pthreadpool_tevent *main,
2367 const char *location)
2369 struct smbd_impersonate_tp_root_state *state =
2370 talloc_get_type_abort(private_data,
2371 struct smbd_impersonate_tp_root_state);
2375 * Move to a non root token again.
2376 * We just use the one of the user_ev_ctx.
2378 * The main goal is that we don't leave
2379 * a thread arround with a root token.
2381 ret = set_thread_credentials(state->fallback_token->uid,
2382 state->fallback_token->gid,
2383 (size_t)state->fallback_token->ngroups,
2384 state->fallback_token->groups);
2392 static const struct pthreadpool_tevent_wrapper_ops smbd_impersonate_tp_root_ops = {
2393 .name = "smbd_impersonate_tp_root",
2394 .before_job = smbd_impersonate_tp_root_before_job,
2395 .after_job = smbd_impersonate_tp_root_after_job,
2398 static struct pthreadpool_tevent *smbd_impersonate_tp_root_create(
2399 TALLOC_CTX *mem_ctx,
2400 struct pthreadpool_tevent *main_tp,
2402 const struct security_unix_token *fallback_token)
2404 struct pthreadpool_tevent *wrap_tp = NULL;
2405 struct smbd_impersonate_tp_root_state *state = NULL;
2408 max_threads = pthreadpool_tevent_max_threads(main_tp);
2409 SMB_ASSERT(max_threads > 0);
2411 wrap_tp = pthreadpool_tevent_wrapper_create(main_tp,
2413 &smbd_impersonate_tp_root_ops,
2415 struct smbd_impersonate_tp_root_state);
2416 if (wrap_tp == NULL) {
2420 state->fallback_token = copy_unix_token(state, fallback_token);
2421 if (state->fallback_token == NULL) {
2422 int saved_errno = errno;
2423 TALLOC_FREE(wrap_tp);
2424 errno = saved_errno;
2431 static struct smb_vfs_ev_glue *smbd_impersonate_user_ev_glue_create(
2432 struct connection_struct *conn,
2434 struct auth_session_info *session_info)
2436 TALLOC_CTX *frame = talloc_stackframe();
2437 struct smb_vfs_ev_glue *user_vfs_evg = NULL;
2438 struct tevent_context *user_ev_ctx = NULL;
2439 struct pthreadpool_tevent *user_tp_fd_safe = NULL;
2440 struct pthreadpool_tevent *user_tp_path_safe = NULL;
2441 bool user_tp_path_sync = true;
2442 struct pthreadpool_tevent *user_tp_chdir_safe = NULL;
2443 bool user_tp_chdir_sync = true;
2444 struct pthreadpool_tevent *root_tp_fd_safe = NULL;
2445 struct pthreadpool_tevent *root_tp_path_safe = NULL;
2446 bool root_tp_path_sync = true;
2447 struct pthreadpool_tevent *root_tp_chdir_safe = NULL;
2448 bool root_tp_chdir_sync = true;
2451 if (vuid == UID_FIELD_INVALID) {
2452 user_ev_ctx = smbd_impersonate_conn_sess_create(
2453 conn->sconn->raw_ev_ctx, conn, session_info);
2454 if (user_ev_ctx == NULL) {
2459 user_ev_ctx = smbd_impersonate_conn_vuid_create(
2460 conn->sconn->raw_ev_ctx, conn, vuid);
2461 if (user_ev_ctx == NULL) {
2466 SMB_ASSERT(talloc_reparent(conn, frame, user_ev_ctx));
2468 #ifdef HAVE_LINUX_THREAD_CREDENTIALS
2469 user_tp_path_sync = lp_parm_bool(SNUM(conn),
2471 "force sync user path safe threadpool",
2473 user_tp_chdir_sync = lp_parm_bool(SNUM(conn),
2475 "force sync user chdir safe threadpool",
2477 root_tp_path_sync = lp_parm_bool(SNUM(conn),
2479 "force sync root path safe threadpool",
2481 root_tp_chdir_sync = lp_parm_bool(SNUM(conn),
2483 "force sync root chdir safe threadpool",
2487 max_threads = pthreadpool_tevent_max_threads(conn->sconn->raw_thread_pool);
2488 if (max_threads == 0) {
2490 * We don't have real threads, so we need to force
2491 * the sync versions...
2493 user_tp_path_sync = true;
2494 user_tp_chdir_sync = true;
2495 root_tp_path_sync = true;
2496 root_tp_chdir_sync = true;
2500 * fd_safe is easy :-)
2502 user_tp_fd_safe = conn->sconn->raw_thread_pool;
2503 root_tp_fd_safe = conn->sconn->raw_thread_pool;
2505 if (user_tp_path_sync) {
2507 * We don't have support for per thread credentials,
2508 * so we just provide a sync thread pool with a wrapper
2509 * that asserts that we are already in the required
2510 * impersonation state.
2512 user_tp_path_safe = smbd_impersonate_tp_current_create(conn,
2513 conn->sconn->sync_thread_pool,
2516 false, /* chdir_safe */
2517 session_info->unix_token);
2518 if (user_tp_path_safe == NULL) {
2523 user_tp_path_safe = smbd_impersonate_tp_sess_create(conn,
2524 conn->sconn->raw_thread_pool,
2526 if (user_tp_path_safe == NULL) {
2531 SMB_ASSERT(talloc_reparent(conn, frame, user_tp_path_safe));
2533 if (pthreadpool_tevent_per_thread_cwd(user_tp_path_safe)) {
2534 user_tp_chdir_safe = user_tp_path_safe;
2536 user_tp_chdir_sync = true;
2539 if (user_tp_chdir_sync) {
2541 * We don't have support for per thread credentials,
2542 * so we just provide a sync thread pool with a wrapper
2543 * that asserts that we are already in the required
2544 * impersonation state.
2546 * And it needs to cleanup after [f]chdir() within
2549 user_tp_chdir_safe = smbd_impersonate_tp_current_create(conn,
2550 conn->sconn->sync_thread_pool,
2553 true, /* chdir_safe */
2554 session_info->unix_token);
2555 if (user_tp_chdir_safe == NULL) {
2559 SMB_ASSERT(talloc_reparent(conn, frame, user_tp_chdir_safe));
2561 SMB_ASSERT(user_tp_chdir_safe != NULL);
2564 if (root_tp_path_sync) {
2566 * We don't have support for per thread credentials,
2567 * so we just provide a sync thread pool with a wrapper
2568 * that wrapps the job in become_root()/unbecome_root().
2570 root_tp_path_safe = smbd_impersonate_tp_become_create(conn,
2571 conn->sconn->sync_thread_pool,
2572 false, /* chdir_safe */
2575 if (root_tp_path_safe == NULL) {
2580 root_tp_path_safe = smbd_impersonate_tp_root_create(conn,
2581 conn->sconn->raw_thread_pool,
2583 session_info->unix_token);
2584 if (root_tp_path_safe == NULL) {
2589 SMB_ASSERT(talloc_reparent(conn, frame, root_tp_path_safe));
2591 if (pthreadpool_tevent_per_thread_cwd(root_tp_path_safe)) {
2592 root_tp_chdir_safe = root_tp_path_safe;
2594 root_tp_chdir_sync = true;
2597 if (root_tp_chdir_sync) {
2599 * We don't have support for per thread credentials,
2600 * so we just provide a sync thread pool with a wrapper
2601 * that wrapps the job in become_root()/unbecome_root().
2603 * And it needs to cleanup after [f]chdir() within
2606 root_tp_chdir_safe = smbd_impersonate_tp_become_create(conn,
2607 conn->sconn->sync_thread_pool,
2608 true, /* chdir_safe */
2611 if (root_tp_chdir_safe == NULL) {
2615 SMB_ASSERT(talloc_reparent(conn, frame, root_tp_chdir_safe));
2617 SMB_ASSERT(root_tp_chdir_safe != NULL);
2620 user_vfs_evg = smb_vfs_ev_glue_create(conn,
2625 conn->sconn->root_ev_ctx,
2628 root_tp_chdir_safe);
2629 if (user_vfs_evg == NULL) {
2635 * Make sure everything is a talloc child of user_vfs_evg
2637 SMB_ASSERT(talloc_reparent(frame, user_vfs_evg, user_ev_ctx));
2638 SMB_ASSERT(talloc_reparent(frame, user_vfs_evg, user_tp_path_safe));
2639 if (user_tp_path_safe != user_tp_chdir_safe) {
2640 SMB_ASSERT(talloc_reparent(frame, user_vfs_evg, user_tp_chdir_safe));
2642 SMB_ASSERT(talloc_reparent(frame, user_vfs_evg, root_tp_path_safe));
2643 if (root_tp_path_safe != root_tp_chdir_safe) {
2644 SMB_ASSERT(talloc_reparent(frame, user_vfs_evg, root_tp_chdir_safe));
2648 return user_vfs_evg;