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 "lib/util/time_basic.h"
30 #include "lib/pthreadpool/pthreadpool_tevent.h"
32 static struct smb_vfs_ev_glue
*smbd_impersonate_user_ev_glue_create(
33 struct connection_struct
*conn
,
35 struct auth_session_info
*session_info
);
37 struct smbd_impersonate_debug_state
{
42 static bool smbd_impersonate_debug_before_use(struct tevent_context
*wrap_ev
,
44 struct tevent_context
*main_ev
,
47 struct smbd_impersonate_debug_state
*state
=
48 (struct smbd_impersonate_debug_state
*)private_data
;
50 DEBUG(state
->dbg_lvl
, (
51 "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] location[%s]\n",
52 __func__
, state
->name
, wrap_ev
, state
, main_ev
, location
));
57 static void smbd_impersonate_debug_after_use(struct tevent_context
*wrap_ev
,
59 struct tevent_context
*main_ev
,
62 struct smbd_impersonate_debug_state
*state
=
63 (struct smbd_impersonate_debug_state
*)private_data
;
65 DEBUG(state
->dbg_lvl
, (
66 "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] location[%s]\n",
67 __func__
, state
->name
, wrap_ev
, state
, main_ev
, location
));
70 static void smbd_impersonate_debug_before_fd_handler(struct tevent_context
*wrap_ev
,
72 struct tevent_context
*main_ev
,
73 struct tevent_fd
*fde
,
75 const char *handler_name
,
78 struct smbd_impersonate_debug_state
*state
=
79 (struct smbd_impersonate_debug_state
*)private_data
;
81 DEBUG(state
->dbg_lvl
, (
82 "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] "
83 "fde[%p] flags[0x%X] handler_name[%s] location[%s]\n",
84 __func__
, state
->name
, wrap_ev
, state
, main_ev
,
85 fde
, flags
, handler_name
, location
));
88 static void smbd_impersonate_debug_after_fd_handler(struct tevent_context
*wrap_ev
,
90 struct tevent_context
*main_ev
,
91 struct tevent_fd
*fde
,
93 const char *handler_name
,
96 struct smbd_impersonate_debug_state
*state
=
97 (struct smbd_impersonate_debug_state
*)private_data
;
99 DEBUG(state
->dbg_lvl
, (
100 "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] "
101 "fde[%p] flags[0x%X] handler_name[%s] location[%s]\n",
102 __func__
, state
->name
, wrap_ev
, state
, main_ev
,
103 fde
, flags
, handler_name
, location
));
106 static void smbd_impersonate_debug_before_timer_handler(struct tevent_context
*wrap_ev
,
108 struct tevent_context
*main_ev
,
109 struct tevent_timer
*te
,
110 struct timeval requested_time
,
111 struct timeval trigger_time
,
112 const char *handler_name
,
113 const char *location
)
115 struct smbd_impersonate_debug_state
*state
=
116 (struct smbd_impersonate_debug_state
*)private_data
;
117 struct timeval_buf requested_buf
;
118 struct timeval_buf trigger_buf
;
120 DEBUG(state
->dbg_lvl
, (
121 "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] "
122 "te[%p] requested_time[%s] trigger_time[%s] handler_name[%s] location[%s]\n",
123 __func__
, state
->name
, wrap_ev
, state
, main_ev
, te
,
124 timeval_str_buf(&requested_time
, true, true, &requested_buf
),
125 timeval_str_buf(&trigger_time
, true, true, &trigger_buf
),
126 handler_name
, location
));
129 static void smbd_impersonate_debug_after_timer_handler(struct tevent_context
*wrap_ev
,
131 struct tevent_context
*main_ev
,
132 struct tevent_timer
*te
,
133 struct timeval requested_time
,
134 struct timeval trigger_time
,
135 const char *handler_name
,
136 const char *location
)
138 struct smbd_impersonate_debug_state
*state
=
139 (struct smbd_impersonate_debug_state
*)private_data
;
140 struct timeval_buf requested_buf
;
141 struct timeval_buf trigger_buf
;
143 DEBUG(state
->dbg_lvl
, (
144 "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] "
145 "te[%p] requested_time[%s] trigger_time[%s] handler_name[%s] location[%s]\n",
146 __func__
, state
->name
, wrap_ev
, state
, main_ev
, te
,
147 timeval_str_buf(&requested_time
, true, true, &requested_buf
),
148 timeval_str_buf(&trigger_time
, true, true, &trigger_buf
),
149 handler_name
, location
));
152 static void smbd_impersonate_debug_before_immediate_handler(struct tevent_context
*wrap_ev
,
154 struct tevent_context
*main_ev
,
155 struct tevent_immediate
*im
,
156 const char *handler_name
,
157 const char *location
)
159 struct smbd_impersonate_debug_state
*state
=
160 (struct smbd_impersonate_debug_state
*)private_data
;
162 DEBUG(state
->dbg_lvl
, (
163 "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] "
164 "im[%p] handler_name[%s] location[%s]\n",
165 __func__
, state
->name
, wrap_ev
, state
, main_ev
,
166 im
, handler_name
, location
));
169 static void smbd_impersonate_debug_after_immediate_handler(struct tevent_context
*wrap_ev
,
171 struct tevent_context
*main_ev
,
172 struct tevent_immediate
*im
,
173 const char *handler_name
,
174 const char *location
)
176 struct smbd_impersonate_debug_state
*state
=
177 (struct smbd_impersonate_debug_state
*)private_data
;
179 DEBUG(state
->dbg_lvl
, (
180 "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] "
181 "im[%p] handler_name[%s] location[%s]\n",
182 __func__
, state
->name
, wrap_ev
, state
, main_ev
,
183 im
, handler_name
, location
));
186 static void smbd_impersonate_debug_before_signal_handler(struct tevent_context
*wrap_ev
,
188 struct tevent_context
*main_ev
,
189 struct tevent_signal
*se
,
193 const char *handler_name
,
194 const char *location
)
196 struct smbd_impersonate_debug_state
*state
=
197 (struct smbd_impersonate_debug_state
*)private_data
;
199 DEBUG(state
->dbg_lvl
, (
200 "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] "
201 "se[%p] signum[%d] count[%d] siginfo[%p] handler_name[%s] location[%s]\n",
202 __func__
, state
->name
, wrap_ev
, state
, main_ev
,
203 se
, signum
, count
, siginfo
, handler_name
, location
));
206 static void smbd_impersonate_debug_after_signal_handler(struct tevent_context
*wrap_ev
,
208 struct tevent_context
*main_ev
,
209 struct tevent_signal
*se
,
213 const char *handler_name
,
214 const char *location
)
216 struct smbd_impersonate_debug_state
*state
=
217 (struct smbd_impersonate_debug_state
*)private_data
;
219 DEBUG(state
->dbg_lvl
, (
220 "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] "
221 "se[%p] signum[%d] count[%d] siginfo[%p] handler_name[%s] location[%s]\n",
222 __func__
, state
->name
, wrap_ev
, state
, main_ev
,
223 se
, signum
, count
, siginfo
, handler_name
, location
));
226 static const struct tevent_wrapper_ops smbd_impersonate_debug_ops
= {
227 .name
= "smbd_impersonate_debug",
228 .before_use
= smbd_impersonate_debug_before_use
,
229 .after_use
= smbd_impersonate_debug_after_use
,
230 .before_fd_handler
= smbd_impersonate_debug_before_fd_handler
,
231 .after_fd_handler
= smbd_impersonate_debug_after_fd_handler
,
232 .before_timer_handler
= smbd_impersonate_debug_before_timer_handler
,
233 .after_timer_handler
= smbd_impersonate_debug_after_timer_handler
,
234 .before_immediate_handler
= smbd_impersonate_debug_before_immediate_handler
,
235 .after_immediate_handler
= smbd_impersonate_debug_after_immediate_handler
,
236 .before_signal_handler
= smbd_impersonate_debug_before_signal_handler
,
237 .after_signal_handler
= smbd_impersonate_debug_after_signal_handler
,
240 struct tevent_context
*_smbd_impersonate_debug_create(struct tevent_context
*main_ev
,
243 const char *location
)
245 struct tevent_context
*wrap_ev
= NULL
;
246 struct smbd_impersonate_debug_state
*state
= NULL
;
248 wrap_ev
= tevent_context_wrapper_create(main_ev
,
250 &smbd_impersonate_debug_ops
,
252 struct smbd_impersonate_debug_state
);
253 if (wrap_ev
== NULL
) {
257 state
->dbg_lvl
= dbg_lvl
;
258 DEBUG(state
->dbg_lvl
, (
259 "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] location[%s]\n",
260 __func__
, state
->name
, wrap_ev
, state
, main_ev
, location
));
265 /* what user is current? */
266 extern struct current_user current_user
;
268 /****************************************************************************
269 Become the guest user without changing the security context stack.
270 ****************************************************************************/
272 bool change_to_guest(void)
276 pass
= Get_Pwnam_alloc(talloc_tos(), lp_guest_account());
282 /* MWW: From AIX FAQ patch to WU-ftpd: call initgroups before
284 initgroups(pass
->pw_name
, pass
->pw_gid
);
287 set_sec_ctx(pass
->pw_uid
, pass
->pw_gid
, 0, NULL
, NULL
);
289 current_user
.conn
= NULL
;
290 current_user
.vuid
= UID_FIELD_INVALID
;
291 current_user
.need_chdir
= false;
292 current_user
.done_chdir
= false;
299 /****************************************************************************
300 talloc free the conn->session_info if not used in the vuid cache.
301 ****************************************************************************/
303 static void free_conn_session_info_if_unused(connection_struct
*conn
)
307 for (i
= 0; i
< VUID_CACHE_SIZE
; i
++) {
308 struct vuid_cache_entry
*ent
;
309 ent
= &conn
->vuid_cache
->array
[i
];
310 if (ent
->vuid
!= UID_FIELD_INVALID
&&
311 conn
->session_info
== ent
->session_info
) {
315 /* Not used, safe to free. */
316 conn
->user_ev_ctx
= NULL
;
317 TALLOC_FREE(conn
->user_vfs_evg
);
318 TALLOC_FREE(conn
->session_info
);
321 /****************************************************************************
322 Setup the share access mask for a connection.
323 ****************************************************************************/
325 static uint32_t create_share_access_mask(int snum
,
327 const struct security_token
*token
)
329 uint32_t share_access
= 0;
331 share_access_check(token
,
332 lp_const_servicename(snum
),
333 MAXIMUM_ALLOWED_ACCESS
,
336 if (readonly_share
) {
338 ~(SEC_FILE_WRITE_DATA
| SEC_FILE_APPEND_DATA
|
339 SEC_FILE_WRITE_EA
| SEC_FILE_WRITE_ATTRIBUTE
|
340 SEC_DIR_DELETE_CHILD
);
343 if (security_token_has_privilege(token
, SEC_PRIV_SECURITY
)) {
344 share_access
|= SEC_FLAG_SYSTEM_SECURITY
;
346 if (security_token_has_privilege(token
, SEC_PRIV_RESTORE
)) {
347 share_access
|= SEC_RIGHTS_PRIV_RESTORE
;
349 if (security_token_has_privilege(token
, SEC_PRIV_BACKUP
)) {
350 share_access
|= SEC_RIGHTS_PRIV_BACKUP
;
352 if (security_token_has_privilege(token
, SEC_PRIV_TAKE_OWNERSHIP
)) {
353 share_access
|= SEC_STD_WRITE_OWNER
;
359 /*******************************************************************
360 Calculate access mask and if this user can access this share.
361 ********************************************************************/
363 NTSTATUS
check_user_share_access(connection_struct
*conn
,
364 const struct auth_session_info
*session_info
,
365 uint32_t *p_share_access
,
366 bool *p_readonly_share
)
368 int snum
= SNUM(conn
);
369 uint32_t share_access
= 0;
370 bool readonly_share
= false;
372 if (!user_ok_token(session_info
->unix_info
->unix_name
,
373 session_info
->info
->domain_name
,
374 session_info
->security_token
, snum
)) {
375 return NT_STATUS_ACCESS_DENIED
;
378 readonly_share
= is_share_read_only_for_token(
379 session_info
->unix_info
->unix_name
,
380 session_info
->info
->domain_name
,
381 session_info
->security_token
,
384 share_access
= create_share_access_mask(snum
,
386 session_info
->security_token
);
388 if ((share_access
& (FILE_READ_DATA
|FILE_WRITE_DATA
)) == 0) {
389 /* No access, read or write. */
390 DBG_NOTICE("user %s connection to %s denied due to share "
391 "security descriptor.\n",
392 session_info
->unix_info
->unix_name
,
393 lp_const_servicename(snum
));
394 return NT_STATUS_ACCESS_DENIED
;
397 if (!readonly_share
&&
398 !(share_access
& FILE_WRITE_DATA
)) {
399 /* smb.conf allows r/w, but the security descriptor denies
400 * write. Fall back to looking at readonly. */
401 readonly_share
= true;
402 DBG_INFO("falling back to read-only access-evaluation due to "
403 "security descriptor\n");
406 *p_share_access
= share_access
;
407 *p_readonly_share
= readonly_share
;
412 /*******************************************************************
413 Check if a username is OK.
415 This sets up conn->session_info with a copy related to this vuser that
416 later code can then mess with.
417 ********************************************************************/
419 static bool check_user_ok(connection_struct
*conn
,
421 const struct auth_session_info
*session_info
,
425 bool readonly_share
= false;
426 bool admin_user
= false;
427 struct vuid_cache_entry
*ent
= NULL
;
428 uint32_t share_access
= 0;
431 for (i
=0; i
<VUID_CACHE_SIZE
; i
++) {
432 ent
= &conn
->vuid_cache
->array
[i
];
433 if (ent
->vuid
== vuid
) {
434 if (vuid
== UID_FIELD_INVALID
) {
436 * Slow path, we don't care
437 * about the array traversal.
441 free_conn_session_info_if_unused(conn
);
442 conn
->session_info
= ent
->session_info
;
443 conn
->user_vfs_evg
= ent
->user_vfs_evg
;
444 conn
->read_only
= ent
->read_only
;
445 conn
->share_access
= ent
->share_access
;
446 conn
->vuid
= ent
->vuid
;
447 conn
->user_ev_ctx
= smb_vfs_ev_glue_ev_ctx(
449 SMB_ASSERT(conn
->user_ev_ctx
!= NULL
);
454 status
= check_user_share_access(conn
,
458 if (!NT_STATUS_IS_OK(status
)) {
462 admin_user
= token_contains_name_in_list(
463 session_info
->unix_info
->unix_name
,
464 session_info
->info
->domain_name
,
465 NULL
, session_info
->security_token
, lp_admin_users(snum
));
467 ent
= &conn
->vuid_cache
->array
[conn
->vuid_cache
->next_entry
];
469 conn
->vuid_cache
->next_entry
=
470 (conn
->vuid_cache
->next_entry
+ 1) % VUID_CACHE_SIZE
;
472 TALLOC_FREE(ent
->session_info
);
475 * If force_user was set, all session_info's are based on the same
476 * username-based faked one.
479 ent
->session_info
= copy_session_info(
480 conn
, conn
->force_user
? conn
->session_info
: session_info
);
482 if (ent
->session_info
== NULL
) {
483 ent
->vuid
= UID_FIELD_INVALID
;
488 DEBUG(2,("check_user_ok: user %s is an admin user. "
489 "Setting uid as %d\n",
490 ent
->session_info
->unix_info
->unix_name
,
491 sec_initial_uid() ));
492 ent
->session_info
->unix_token
->uid
= sec_initial_uid();
495 ent
->user_vfs_evg
= smbd_impersonate_user_ev_glue_create(conn
,
496 vuid
, ent
->session_info
);
497 if (ent
->user_vfs_evg
== NULL
) {
498 TALLOC_FREE(ent
->session_info
);
499 ent
->vuid
= UID_FIELD_INVALID
;
504 * It's actually OK to call check_user_ok() with
505 * vuid == UID_FIELD_INVALID as called from change_to_user_by_session().
506 * All this will do is throw away one entry in the cache.
510 ent
->read_only
= readonly_share
;
511 ent
->share_access
= share_access
;
512 free_conn_session_info_if_unused(conn
);
513 conn
->session_info
= ent
->session_info
;
514 conn
->vuid
= ent
->vuid
;
515 conn
->user_vfs_evg
= ent
->user_vfs_evg
;
516 conn
->user_ev_ctx
= smb_vfs_ev_glue_ev_ctx(conn
->user_vfs_evg
);
517 SMB_ASSERT(conn
->user_ev_ctx
!= NULL
);
519 if (vuid
== UID_FIELD_INVALID
) {
521 * Not strictly needed, just make it really
522 * clear this entry is actually an unused one.
524 ent
->read_only
= false;
525 ent
->share_access
= 0;
526 ent
->session_info
= NULL
;
527 ent
->user_vfs_evg
= NULL
;
530 conn
->read_only
= readonly_share
;
531 conn
->share_access
= share_access
;
536 /****************************************************************************
537 Become the user of a connection number without changing the security context
538 stack, but modify the current_user entries.
539 ****************************************************************************/
541 static bool change_to_user_internal(connection_struct
*conn
,
542 const struct auth_session_info
*session_info
,
550 gid_t
*group_list
= NULL
;
553 if ((current_user
.conn
== conn
) &&
554 (current_user
.vuid
== vuid
) &&
555 (current_user
.need_chdir
== conn
->tcon_done
) &&
556 (current_user
.ut
.uid
== session_info
->unix_token
->uid
))
558 DBG_INFO("Skipping user change - already user\n");
562 set_current_user_info(session_info
->unix_info
->sanitized_username
,
563 session_info
->unix_info
->unix_name
,
564 session_info
->info
->domain_name
);
568 ok
= check_user_ok(conn
, vuid
, session_info
, snum
);
570 DBG_WARNING("SMB user %s (unix user %s) "
571 "not permitted access to share %s.\n",
572 session_info
->unix_info
->sanitized_username
,
573 session_info
->unix_info
->unix_name
,
574 lp_const_servicename(snum
));
578 uid
= conn
->session_info
->unix_token
->uid
;
579 gid
= conn
->session_info
->unix_token
->gid
;
580 num_groups
= conn
->session_info
->unix_token
->ngroups
;
581 group_list
= conn
->session_info
->unix_token
->groups
;
584 * See if we should force group for this service. If so this overrides
585 * any group set in the force user code.
587 if((group_c
= *lp_force_group(talloc_tos(), snum
))) {
589 SMB_ASSERT(conn
->force_group_gid
!= (gid_t
)-1);
591 if (group_c
== '+') {
595 * Only force group if the user is a member of the
596 * service group. Check the group memberships for this
597 * user (we already have this) to see if we should force
600 for (i
= 0; i
< num_groups
; i
++) {
601 if (group_list
[i
] == conn
->force_group_gid
) {
602 conn
->session_info
->unix_token
->gid
=
603 conn
->force_group_gid
;
604 gid
= conn
->force_group_gid
;
605 gid_to_sid(&conn
->session_info
->security_token
611 conn
->session_info
->unix_token
->gid
= conn
->force_group_gid
;
612 gid
= conn
->force_group_gid
;
613 gid_to_sid(&conn
->session_info
->security_token
->sids
[1],
618 /*Set current_user since we will immediately also call set_sec_ctx() */
619 current_user
.ut
.ngroups
= num_groups
;
620 current_user
.ut
.groups
= group_list
;
624 current_user
.ut
.ngroups
,
625 current_user
.ut
.groups
,
626 conn
->session_info
->security_token
);
628 current_user
.conn
= conn
;
629 current_user
.vuid
= vuid
;
630 current_user
.need_chdir
= conn
->tcon_done
;
632 if (current_user
.need_chdir
) {
633 ok
= chdir_current_service(conn
);
635 DBG_ERR("chdir_current_service() failed!\n");
638 current_user
.done_chdir
= true;
641 if (CHECK_DEBUGLVL(DBGLVL_INFO
)) {
642 struct smb_filename
*cwdfname
= vfs_GetWd(talloc_tos(), conn
);
643 if (cwdfname
== NULL
) {
646 DBG_INFO("Impersonated user: uid=(%d,%d), gid=(%d,%d), cwd=[%s]\n",
651 cwdfname
->base_name
);
652 TALLOC_FREE(cwdfname
);
658 bool change_to_user(connection_struct
*conn
, uint64_t vuid
)
660 struct user_struct
*vuser
;
661 int snum
= SNUM(conn
);
664 DEBUG(2,("Connection not open\n"));
668 vuser
= get_valid_user_struct(conn
->sconn
, vuid
);
670 /* Invalid vuid sent */
671 DBG_WARNING("Invalid vuid %llu used on share %s.\n",
672 (unsigned long long)vuid
,
673 lp_const_servicename(snum
));
677 return change_to_user_internal(conn
, vuser
->session_info
, vuid
);
680 bool change_to_user_by_fsp(struct files_struct
*fsp
)
682 return change_to_user(fsp
->conn
, fsp
->vuid
);
685 static bool change_to_user_by_session(connection_struct
*conn
,
686 const struct auth_session_info
*session_info
)
688 SMB_ASSERT(conn
!= NULL
);
689 SMB_ASSERT(session_info
!= NULL
);
691 return change_to_user_internal(conn
, session_info
, UID_FIELD_INVALID
);
694 /****************************************************************************
695 Go back to being root without changing the security context stack,
696 but modify the current_user entries.
697 ****************************************************************************/
699 bool smbd_change_to_root_user(void)
703 DEBUG(5,("change_to_root_user: now uid=(%d,%d) gid=(%d,%d)\n",
704 (int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid()));
706 current_user
.conn
= NULL
;
707 current_user
.vuid
= UID_FIELD_INVALID
;
708 current_user
.need_chdir
= false;
709 current_user
.done_chdir
= false;
714 /****************************************************************************
715 Become the user of an authenticated connected named pipe.
716 When this is called we are currently running as the connection
717 user. Doesn't modify current_user.
718 ****************************************************************************/
720 bool smbd_become_authenticated_pipe_user(struct auth_session_info
*session_info
)
725 set_sec_ctx(session_info
->unix_token
->uid
, session_info
->unix_token
->gid
,
726 session_info
->unix_token
->ngroups
, session_info
->unix_token
->groups
,
727 session_info
->security_token
);
729 DEBUG(5, ("Impersonated user: uid=(%d,%d), gid=(%d,%d)\n",
738 /****************************************************************************
739 Unbecome the user of an authenticated connected named pipe.
740 When this is called we are running as the authenticated pipe
741 user and need to go back to being the connection user. Doesn't modify
743 ****************************************************************************/
745 bool smbd_unbecome_authenticated_pipe_user(void)
747 return pop_sec_ctx();
750 /****************************************************************************
751 Utility functions used by become_xxx/unbecome_xxx.
752 ****************************************************************************/
754 static void push_conn_ctx(void)
756 struct conn_ctx
*ctx_p
;
757 extern userdom_struct current_user_info
;
759 /* Check we don't overflow our stack */
761 if (conn_ctx_stack_ndx
== MAX_SEC_CTX_DEPTH
) {
762 DEBUG(0, ("Connection context stack overflow!\n"));
763 smb_panic("Connection context stack overflow!\n");
766 /* Store previous user context */
767 ctx_p
= &conn_ctx_stack
[conn_ctx_stack_ndx
];
769 ctx_p
->conn
= current_user
.conn
;
770 ctx_p
->vuid
= current_user
.vuid
;
771 ctx_p
->need_chdir
= current_user
.need_chdir
;
772 ctx_p
->done_chdir
= current_user
.done_chdir
;
773 ctx_p
->user_info
= current_user_info
;
775 DEBUG(4, ("push_conn_ctx(%llu) : conn_ctx_stack_ndx = %d\n",
776 (unsigned long long)ctx_p
->vuid
, conn_ctx_stack_ndx
));
778 conn_ctx_stack_ndx
++;
781 static void pop_conn_ctx(void)
783 struct conn_ctx
*ctx_p
;
785 /* Check for stack underflow. */
787 if (conn_ctx_stack_ndx
== 0) {
788 DEBUG(0, ("Connection context stack underflow!\n"));
789 smb_panic("Connection context stack underflow!\n");
792 conn_ctx_stack_ndx
--;
793 ctx_p
= &conn_ctx_stack
[conn_ctx_stack_ndx
];
795 set_current_user_info(ctx_p
->user_info
.smb_name
,
796 ctx_p
->user_info
.unix_name
,
797 ctx_p
->user_info
.domain
);
800 * Check if the current context did a chdir_current_service()
801 * and restore the cwd_fname of the previous context
804 if (current_user
.done_chdir
&& ctx_p
->need_chdir
) {
807 ret
= vfs_ChDir(ctx_p
->conn
, ctx_p
->conn
->cwd_fname
);
809 DBG_ERR("vfs_ChDir() failed!\n");
810 smb_panic("vfs_ChDir() failed!\n");
814 current_user
.conn
= ctx_p
->conn
;
815 current_user
.vuid
= ctx_p
->vuid
;
816 current_user
.need_chdir
= ctx_p
->need_chdir
;
817 current_user
.done_chdir
= ctx_p
->done_chdir
;
819 *ctx_p
= (struct conn_ctx
) {
820 .vuid
= UID_FIELD_INVALID
,
824 /****************************************************************************
825 Temporarily become a root user. Must match with unbecome_root(). Saves and
826 restores the connection context.
827 ****************************************************************************/
829 void smbd_become_root(void)
832 * no good way to handle push_sec_ctx() failing without changing
833 * the prototype of become_root()
835 if (!push_sec_ctx()) {
836 smb_panic("become_root: push_sec_ctx failed");
842 /* Unbecome the root user */
844 void smbd_unbecome_root(void)
850 bool become_guest(void)
861 ok
= change_to_guest();
871 void unbecome_guest(void)
878 /****************************************************************************
879 Push the current security context then force a change via change_to_user().
880 Saves and restores the connection context.
881 ****************************************************************************/
883 bool become_user(connection_struct
*conn
, uint64_t vuid
)
890 if (!change_to_user(conn
, vuid
)) {
899 bool become_user_by_fsp(struct files_struct
*fsp
)
901 return become_user(fsp
->conn
, fsp
->vuid
);
904 bool become_user_by_session(connection_struct
*conn
,
905 const struct auth_session_info
*session_info
)
912 if (!change_to_user_by_session(conn
, session_info
)) {
921 bool unbecome_user(void)
928 /****************************************************************************
929 Return the current user we are running effectively as on this connection.
930 I'd like to make this return conn->session_info->unix_token->uid, but become_root()
931 doesn't alter this value.
932 ****************************************************************************/
934 uid_t
get_current_uid(connection_struct
*conn
)
936 return current_user
.ut
.uid
;
939 /****************************************************************************
940 Return the current group we are running effectively as on this connection.
941 I'd like to make this return conn->session_info->unix_token->gid, but become_root()
942 doesn't alter this value.
943 ****************************************************************************/
945 gid_t
get_current_gid(connection_struct
*conn
)
947 return current_user
.ut
.gid
;
950 /****************************************************************************
951 Return the UNIX token we are running effectively as on this connection.
952 I'd like to make this return &conn->session_info->unix_token-> but become_root()
953 doesn't alter this value.
954 ****************************************************************************/
956 const struct security_unix_token
*get_current_utok(connection_struct
*conn
)
958 return ¤t_user
.ut
;
961 /****************************************************************************
962 Return the Windows token we are running effectively as on this connection.
963 If this is currently a NULL token as we're inside become_root() - a temporary
964 UNIX security override, then we search up the stack for the previous active
966 ****************************************************************************/
968 const struct security_token
*get_current_nttok(connection_struct
*conn
)
970 if (current_user
.nt_user_token
) {
971 return current_user
.nt_user_token
;
973 return sec_ctx_active_token();
976 uint64_t get_current_vuid(connection_struct
*conn
)
978 return current_user
.vuid
;
981 struct smbd_impersonate_conn_vuid_state
{
982 struct connection_struct
*conn
;
986 static bool smbd_impersonate_conn_vuid_before_use(
987 struct tevent_context
*wrap_ev
,
989 struct tevent_context
*main_ev
,
990 const char *location
)
992 struct smbd_impersonate_conn_vuid_state
*state
=
993 talloc_get_type_abort(private_data
,
994 struct smbd_impersonate_conn_vuid_state
);
997 DEBUG(11,("%s: wrap_ev[%p] main_ev[%p] location[%s]"
998 "old uid[%ju] old gid[%ju] vuid[%ju] cwd[%s]\n",
999 __func__
, wrap_ev
, main_ev
, location
,
1000 (uintmax_t)geteuid(), (uintmax_t)getegid(),
1001 (uintmax_t)state
->vuid
, state
->conn
->cwd_fname
->base_name
));
1003 ok
= become_user(state
->conn
, state
->vuid
);
1005 smb_panic("smbd_impersonate_conn_vuid_before_use() - failed");
1009 DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1010 __func__
, state
->conn
->session_info
->unix_info
->unix_name
,
1011 (uintmax_t)geteuid(), (uintmax_t)getegid(),
1012 state
->conn
->cwd_fname
->base_name
));
1017 static void smbd_impersonate_conn_vuid_after_use(
1018 struct tevent_context
*wrap_ev
,
1020 struct tevent_context
*main_ev
,
1021 const char *location
)
1023 struct smbd_impersonate_conn_vuid_state
*state
=
1024 talloc_get_type_abort(private_data
,
1025 struct smbd_impersonate_conn_vuid_state
);
1028 DEBUG(11,("%s: deimpersonating[%s] uid[%ju] gid[%ju] cwd[%s] "
1030 __func__
, state
->conn
->session_info
->unix_info
->unix_name
,
1031 (uintmax_t)geteuid(), (uintmax_t)getegid(),
1032 state
->conn
->cwd_fname
->base_name
, location
));
1034 ok
= unbecome_user();
1036 smb_panic("smbd_impersonate_conn_vuid_after_use() - failed");
1040 DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1041 __func__
, state
->conn
->session_info
->unix_info
->unix_name
,
1042 (uintmax_t)geteuid(), (uintmax_t)getegid(),
1043 state
->conn
->cwd_fname
->base_name
));
1046 static void smbd_impersonate_conn_vuid_before_fd_handler(
1047 struct tevent_context
*wrap_ev
,
1049 struct tevent_context
*main_ev
,
1050 struct tevent_fd
*fde
,
1052 const char *handler_name
,
1053 const char *location
)
1055 struct smbd_impersonate_conn_vuid_state
*state
= talloc_get_type_abort(
1056 private_data
, struct smbd_impersonate_conn_vuid_state
);
1059 DEBUG(11,("%s: fde[%p] flags[%ju] handler_name[%s] location[%s]\n",
1060 __func__
, fde
, (uintmax_t)flags
, handler_name
, location
));
1062 ok
= change_to_user(state
->conn
, state
->vuid
);
1064 smb_panic("smbd_impersonate_conn_vuid_before_use() - failed");
1068 DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1069 __func__
, state
->conn
->session_info
->unix_info
->unix_name
,
1070 (uintmax_t)geteuid(), (uintmax_t)getegid(),
1071 state
->conn
->cwd_fname
->base_name
));
1074 static void smbd_impersonate_conn_vuid_after_fd_handler(
1075 struct tevent_context
*wrap_ev
,
1077 struct tevent_context
*main_ev
,
1078 struct tevent_fd
*fde
,
1080 const char *handler_name
,
1081 const char *location
)
1083 DEBUG(11,("%s: fde[%p] handler_name[%s] location[%s]\n",
1084 __func__
, fde
, handler_name
, location
));
1086 /* be lazy and defer change_to_root_user() */
1089 static void smbd_impersonate_conn_vuid_before_timer_handler(
1090 struct tevent_context
*wrap_ev
,
1092 struct tevent_context
*main_ev
,
1093 struct tevent_timer
*te
,
1094 struct timeval requested_time
,
1095 struct timeval trigger_time
,
1096 const char *handler_name
,
1097 const char *location
)
1099 struct smbd_impersonate_conn_vuid_state
*state
= talloc_get_type_abort(
1100 private_data
, struct smbd_impersonate_conn_vuid_state
);
1101 struct timeval_buf requested_buf
;
1102 struct timeval_buf trigger_buf
;
1105 DEBUG(11,("%s: te[%p] requested_time[%s] trigger_time[%s] "
1106 "handler_name[%s] location[%s]\n",
1108 timeval_str_buf(&requested_time
, true, true, &requested_buf
),
1109 timeval_str_buf(&trigger_time
, true, true, &trigger_buf
),
1110 handler_name
, location
));
1112 ok
= change_to_user(state
->conn
, state
->vuid
);
1114 smb_panic("smbd_impersonate_conn_vuid_before_use() - failed");
1118 DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1119 __func__
, state
->conn
->session_info
->unix_info
->unix_name
,
1120 (uintmax_t)geteuid(), (uintmax_t)getegid(),
1121 state
->conn
->cwd_fname
->base_name
));
1124 static void smbd_impersonate_conn_vuid_after_timer_handler(
1125 struct tevent_context
*wrap_ev
,
1127 struct tevent_context
*main_ev
,
1128 struct tevent_timer
*te
,
1129 struct timeval requested_time
,
1130 struct timeval trigger_time
,
1131 const char *handler_name
,
1132 const char *location
)
1134 DEBUG(11,("%s: te[%p] handler_name[%s] location[%s]\n",
1135 __func__
, te
, handler_name
, location
));
1137 /* be lazy and defer change_to_root_user() */
1140 static void smbd_impersonate_conn_vuid_before_immediate_handler(
1141 struct tevent_context
*wrap_ev
,
1143 struct tevent_context
*main_ev
,
1144 struct tevent_immediate
*im
,
1145 const char *handler_name
,
1146 const char *location
)
1148 struct smbd_impersonate_conn_vuid_state
*state
= talloc_get_type_abort(
1149 private_data
, struct smbd_impersonate_conn_vuid_state
);
1152 DEBUG(11,("%s: im[%p] handler_name[%s] location[%s]\n",
1153 __func__
, im
, handler_name
, location
));
1155 ok
= change_to_user(state
->conn
, state
->vuid
);
1157 smb_panic("smbd_impersonate_conn_vuid_before_use() - failed");
1161 DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1162 __func__
, state
->conn
->session_info
->unix_info
->unix_name
,
1163 (uintmax_t)geteuid(), (uintmax_t)getegid(),
1164 state
->conn
->cwd_fname
->base_name
));
1167 static void smbd_impersonate_conn_vuid_after_immediate_handler(
1168 struct tevent_context
*wrap_ev
,
1170 struct tevent_context
*main_ev
,
1171 struct tevent_immediate
*im
,
1172 const char *handler_name
,
1173 const char *location
)
1175 DEBUG(11,("%s: im[%p] handler_name[%s] location[%s]\n",
1176 __func__
, im
, handler_name
, location
));
1178 /* be lazy and defer unbecome_user() */
1181 static void smbd_impersonate_conn_vuid_before_signal_handler(
1182 struct tevent_context
*wrap_ev
,
1184 struct tevent_context
*main_ev
,
1185 struct tevent_signal
*se
,
1189 const char *handler_name
,
1190 const char *location
)
1192 struct smbd_impersonate_conn_vuid_state
*state
= talloc_get_type_abort(
1193 private_data
, struct smbd_impersonate_conn_vuid_state
);
1196 DEBUG(11,("%s: se[%p] signum[%d] count[%d] siginfo[%p] "
1197 "handler_name[%s] location[%s]\n",
1198 __func__
, se
, signum
, count
, siginfo
, handler_name
, location
));
1200 ok
= change_to_user(state
->conn
, state
->vuid
);
1202 smb_panic("smbd_impersonate_conn_vuid_before_use() - failed");
1206 DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1207 __func__
, state
->conn
->session_info
->unix_info
->unix_name
,
1208 (uintmax_t)geteuid(), (uintmax_t)getegid(),
1209 state
->conn
->cwd_fname
->base_name
));
1212 static void smbd_impersonate_conn_vuid_after_signal_handler(
1213 struct tevent_context
*wrap_ev
,
1215 struct tevent_context
*main_ev
,
1216 struct tevent_signal
*se
,
1220 const char *handler_name
,
1221 const char *location
)
1223 DEBUG(11,("%s: se[%p] handler_name[%s] location[%s]\n",
1224 __func__
, se
, handler_name
, location
));
1226 /* be lazy and defer change_to_root_user() */
1229 static const struct tevent_wrapper_ops smbd_impersonate_conn_vuid_ops
= {
1230 .name
= "smbd_impersonate_conn_vuid",
1231 .before_use
= smbd_impersonate_conn_vuid_before_use
,
1232 .after_use
= smbd_impersonate_conn_vuid_after_use
,
1233 .before_fd_handler
= smbd_impersonate_conn_vuid_before_fd_handler
,
1234 .after_fd_handler
= smbd_impersonate_conn_vuid_after_fd_handler
,
1235 .before_timer_handler
= smbd_impersonate_conn_vuid_before_timer_handler
,
1236 .after_timer_handler
= smbd_impersonate_conn_vuid_after_timer_handler
,
1237 .before_immediate_handler
= smbd_impersonate_conn_vuid_before_immediate_handler
,
1238 .after_immediate_handler
= smbd_impersonate_conn_vuid_after_immediate_handler
,
1239 .before_signal_handler
= smbd_impersonate_conn_vuid_before_signal_handler
,
1240 .after_signal_handler
= smbd_impersonate_conn_vuid_after_signal_handler
,
1243 struct tevent_context
*smbd_impersonate_conn_vuid_create(
1244 struct tevent_context
*main_ev
,
1245 struct connection_struct
*conn
,
1248 struct tevent_context
*ev
= NULL
;
1249 struct smbd_impersonate_conn_vuid_state
*state
= NULL
;
1251 ev
= tevent_context_wrapper_create(main_ev
,
1253 &smbd_impersonate_conn_vuid_ops
,
1255 struct smbd_impersonate_conn_vuid_state
);
1265 struct smbd_impersonate_conn_sess_state
{
1266 struct connection_struct
*conn
;
1267 struct auth_session_info
*session_info
;
1270 static bool smbd_impersonate_conn_sess_before_use(struct tevent_context
*wrap_ev
,
1272 struct tevent_context
*main_ev
,
1273 const char *location
)
1275 struct smbd_impersonate_conn_sess_state
*state
= talloc_get_type_abort(
1276 private_data
, struct smbd_impersonate_conn_sess_state
);
1279 DEBUG(11,("%s: impersonating user[%s] wrap_ev[%p] main_ev[%p] "
1280 "location[%s] old uid[%ju] old gid[%ju] cwd[%s]\n",
1281 __func__
, state
->session_info
->unix_info
->unix_name
,
1282 wrap_ev
, main_ev
, location
,
1283 (uintmax_t)geteuid(), (uintmax_t)getegid(),
1284 state
->conn
->cwd_fname
->base_name
));
1286 ok
= become_user_by_session(state
->conn
, state
->session_info
);
1291 DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1292 __func__
, state
->conn
->session_info
->unix_info
->unix_name
,
1293 (uintmax_t)geteuid(), (uintmax_t)getegid(),
1294 state
->conn
->cwd_fname
->base_name
));
1299 static void smbd_impersonate_conn_sess_after_use(struct tevent_context
*wrap_ev
,
1301 struct tevent_context
*main_ev
,
1302 const char *location
)
1304 struct smbd_impersonate_conn_sess_state
*state
= talloc_get_type_abort(
1305 private_data
, struct smbd_impersonate_conn_sess_state
);
1308 DEBUG(11,("%s: deimpersonating[%s] uid[%ju] gid[%ju] cwd[%s] "
1310 __func__
, state
->session_info
->unix_info
->unix_name
,
1311 (uintmax_t)geteuid(), (uintmax_t)getegid(),
1312 state
->conn
->cwd_fname
->base_name
, location
));
1314 ok
= unbecome_user();
1316 smb_panic("smbd_impersonate_conn_sess_after_use() - failed");
1320 DEBUG(11,("%s: deimpersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1321 __func__
, state
->conn
->session_info
->unix_info
->unix_name
,
1322 (uintmax_t)geteuid(), (uintmax_t)getegid(),
1323 state
->conn
->cwd_fname
->base_name
));
1326 static void smbd_impersonate_conn_sess_before_fd_handler(
1327 struct tevent_context
*wrap_ev
,
1329 struct tevent_context
*main_ev
,
1330 struct tevent_fd
*fde
,
1332 const char *handler_name
,
1333 const char *location
)
1335 struct smbd_impersonate_conn_sess_state
*state
= talloc_get_type_abort(
1336 private_data
, struct smbd_impersonate_conn_sess_state
);
1339 DEBUG(11,("%s: fde[%p] flags[%ju] handler_name[%s] location[%s]\n",
1340 __func__
, fde
, (uintmax_t)flags
, handler_name
, location
));
1342 ok
= change_to_user_by_session(state
->conn
, state
->session_info
);
1344 smb_panic("smbd_impersonate_conn_sess_before_fd_handler failed");
1348 DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1349 __func__
, state
->conn
->session_info
->unix_info
->unix_name
,
1350 (uintmax_t)geteuid(), (uintmax_t)getegid(),
1351 state
->conn
->cwd_fname
->base_name
));
1354 static void smbd_impersonate_conn_sess_after_fd_handler(struct tevent_context
*wrap_ev
,
1356 struct tevent_context
*main_ev
,
1357 struct tevent_fd
*fde
,
1359 const char *handler_name
,
1360 const char *location
)
1362 DEBUG(11,("%s: fde[%p] handler_name[%s] location[%s]\n",
1363 __func__
, fde
, handler_name
, location
));
1365 /* be lazy and defer change_to_root_user() */
1368 static void smbd_impersonate_conn_sess_before_timer_handler(
1369 struct tevent_context
*wrap_ev
,
1371 struct tevent_context
*main_ev
,
1372 struct tevent_timer
*te
,
1373 struct timeval requested_time
,
1374 struct timeval trigger_time
,
1375 const char *handler_name
,
1376 const char *location
)
1378 struct smbd_impersonate_conn_sess_state
*state
= talloc_get_type_abort(
1379 private_data
, struct smbd_impersonate_conn_sess_state
);
1380 struct timeval_buf requested_buf
;
1381 struct timeval_buf trigger_buf
;
1384 DEBUG(11,("%s: te[%p] requested_time[%s] trigger_time[%s] "
1385 "handler_name[%s] location[%s]\n",
1387 timeval_str_buf(&requested_time
, true, true, &requested_buf
),
1388 timeval_str_buf(&trigger_time
, true, true, &trigger_buf
),
1389 handler_name
, location
));
1391 ok
= change_to_user_by_session(state
->conn
, state
->session_info
);
1393 smb_panic("smbd_impersonate_conn_sess_before_tm_handler failed");
1397 DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1398 __func__
, state
->conn
->session_info
->unix_info
->unix_name
,
1399 (uintmax_t)geteuid(), (uintmax_t)getegid(),
1400 state
->conn
->cwd_fname
->base_name
));
1403 static void smbd_impersonate_conn_sess_after_timer_handler(
1404 struct tevent_context
*wrap_ev
,
1406 struct tevent_context
*main_ev
,
1407 struct tevent_timer
*te
,
1408 struct timeval requested_time
,
1409 struct timeval trigger_time
,
1410 const char *handler_name
,
1411 const char *location
)
1413 DEBUG(11,("%s: te[%p] handler_name[%s] location[%s]\n",
1414 __func__
, te
, handler_name
, location
));
1416 /* be lazy and defer change_to_root_user() */
1419 static void smbd_impersonate_conn_sess_before_immediate_handler(
1420 struct tevent_context
*wrap_ev
,
1422 struct tevent_context
*main_ev
,
1423 struct tevent_immediate
*im
,
1424 const char *handler_name
,
1425 const char *location
)
1427 struct smbd_impersonate_conn_sess_state
*state
= talloc_get_type_abort(
1428 private_data
, struct smbd_impersonate_conn_sess_state
);
1431 DEBUG(11,("%s: im[%p] handler_name[%s] location[%s]\n",
1432 __func__
, im
, handler_name
, location
));
1434 ok
= change_to_user_by_session(state
->conn
, state
->session_info
);
1436 smb_panic("smbd_impersonate_conn_sess_before_im_handler failed");
1440 DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1441 __func__
, state
->conn
->session_info
->unix_info
->unix_name
,
1442 (uintmax_t)geteuid(), (uintmax_t)getegid(),
1443 state
->conn
->cwd_fname
->base_name
));
1446 static void smbd_impersonate_conn_sess_after_immediate_handler(
1447 struct tevent_context
*wrap_ev
,
1449 struct tevent_context
*main_ev
,
1450 struct tevent_immediate
*im
,
1451 const char *handler_name
,
1452 const char *location
)
1454 DEBUG(11,("%s: im[%p] handler_name[%s] location[%s]\n",
1455 __func__
, im
, handler_name
, location
));
1457 /* be lazy and defer unbecome_user() */
1460 static void smbd_impersonate_conn_sess_before_signal_handler(
1461 struct tevent_context
*wrap_ev
,
1463 struct tevent_context
*main_ev
,
1464 struct tevent_signal
*se
,
1468 const char *handler_name
,
1469 const char *location
)
1471 struct smbd_impersonate_conn_sess_state
*state
= talloc_get_type_abort(
1472 private_data
, struct smbd_impersonate_conn_sess_state
);
1475 DEBUG(11,("%s: se[%p] signum[%d] count[%d] siginfo[%p] "
1476 "handler_name[%s] location[%s]\n",
1477 __func__
, se
, signum
, count
, siginfo
, handler_name
, location
));
1479 ok
= change_to_user_by_session(state
->conn
, state
->session_info
);
1481 smb_panic("smbd_impersonate_conn_sess_before_si_handler failed");
1485 DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1486 __func__
, state
->conn
->session_info
->unix_info
->unix_name
,
1487 (uintmax_t)geteuid(), (uintmax_t)getegid(),
1488 state
->conn
->cwd_fname
->base_name
));
1491 static void smbd_impersonate_conn_sess_after_signal_handler(
1492 struct tevent_context
*wrap_ev
,
1494 struct tevent_context
*main_ev
,
1495 struct tevent_signal
*se
,
1499 const char *handler_name
,
1500 const char *location
)
1502 DEBUG(11,("%s: se[%p] handler_name[%s] location[%s]\n",
1503 __func__
, se
, handler_name
, location
));
1505 /* be lazy and defer change_to_root_user() */
1508 static const struct tevent_wrapper_ops smbd_impersonate_conn_sess_ops
= {
1509 .name
= "smbd_impersonate_conn_sess",
1510 .before_use
= smbd_impersonate_conn_sess_before_use
,
1511 .after_use
= smbd_impersonate_conn_sess_after_use
,
1512 .before_fd_handler
= smbd_impersonate_conn_sess_before_fd_handler
,
1513 .after_fd_handler
= smbd_impersonate_conn_sess_after_fd_handler
,
1514 .before_timer_handler
= smbd_impersonate_conn_sess_before_timer_handler
,
1515 .after_timer_handler
= smbd_impersonate_conn_sess_after_timer_handler
,
1516 .before_immediate_handler
= smbd_impersonate_conn_sess_before_immediate_handler
,
1517 .after_immediate_handler
= smbd_impersonate_conn_sess_after_immediate_handler
,
1518 .before_signal_handler
= smbd_impersonate_conn_sess_before_signal_handler
,
1519 .after_signal_handler
= smbd_impersonate_conn_sess_after_signal_handler
,
1522 struct tevent_context
*smbd_impersonate_conn_sess_create(
1523 struct tevent_context
*main_ev
,
1524 struct connection_struct
*conn
,
1525 struct auth_session_info
*session_info
)
1527 struct tevent_context
*ev
= NULL
;
1528 struct smbd_impersonate_conn_sess_state
*state
= NULL
;
1530 ev
= tevent_context_wrapper_create(main_ev
,
1532 &smbd_impersonate_conn_sess_ops
,
1534 struct smbd_impersonate_conn_sess_state
);
1539 state
->session_info
= session_info
;
1544 struct smbd_impersonate_root_state
{
1548 static bool smbd_impersonate_root_before_use(struct tevent_context
*wrap_ev
,
1550 struct tevent_context
*main_ev
,
1551 const char *location
)
1553 DEBUG(11,("%s: wrap_ev[%p] main_ev[%p] location[%s]"
1554 "uid[%ju] gid[%ju]\n",
1555 __func__
, wrap_ev
, main_ev
, location
,
1556 (uintmax_t)geteuid(), (uintmax_t)getegid()));
1562 static void smbd_impersonate_root_after_use(struct tevent_context
*wrap_ev
,
1564 struct tevent_context
*main_ev
,
1565 const char *location
)
1569 DEBUG(11,("%s: uid[%ju] gid[%ju] location[%s]\n",
1570 __func__
, (uintmax_t)geteuid(), (uintmax_t)getegid(),
1574 static void smbd_impersonate_root_before_fd_handler(struct tevent_context
*wrap_ev
,
1576 struct tevent_context
*main_ev
,
1577 struct tevent_fd
*fde
,
1579 const char *handler_name
,
1580 const char *location
)
1582 DEBUG(11,("%s: fde[%p] flags[%ju] handler_name[%s] location[%s]\n",
1583 __func__
, fde
, (uintmax_t)flags
, handler_name
, location
));
1585 smbd_impersonate_root_before_use(wrap_ev
, private_data
, main_ev
, location
);
1588 static void smbd_impersonate_root_after_fd_handler(struct tevent_context
*wrap_ev
,
1590 struct tevent_context
*main_ev
,
1591 struct tevent_fd
*fde
,
1593 const char *handler_name
,
1594 const char *location
)
1596 DEBUG(11,("%s: fde[%p] handler_name[%s] location[%s]\n",
1597 __func__
, fde
, handler_name
, location
));
1599 smbd_impersonate_root_after_use(wrap_ev
, private_data
, main_ev
, location
);
1602 static void smbd_impersonate_root_before_timer_handler(struct tevent_context
*wrap_ev
,
1604 struct tevent_context
*main_ev
,
1605 struct tevent_timer
*te
,
1606 struct timeval requested_time
,
1607 struct timeval trigger_time
,
1608 const char *handler_name
,
1609 const char *location
)
1611 struct timeval_buf requested_buf
;
1612 struct timeval_buf trigger_buf
;
1614 DEBUG(11,("%s: te[%p] requested_time[%s] trigger_time[%s] "
1615 "handler_name[%s] location[%s]\n",
1617 timeval_str_buf(&requested_time
, true, true, &requested_buf
),
1618 timeval_str_buf(&trigger_time
, true, true, &trigger_buf
),
1619 handler_name
, location
));
1621 smbd_impersonate_root_before_use(wrap_ev
, private_data
, main_ev
, location
);
1624 static void smbd_impersonate_root_after_timer_handler(struct tevent_context
*wrap_ev
,
1626 struct tevent_context
*main_ev
,
1627 struct tevent_timer
*te
,
1628 struct timeval requested_time
,
1629 struct timeval trigger_time
,
1630 const char *handler_name
,
1631 const char *location
)
1633 DEBUG(11,("%s: te[%p] handler_name[%s] location[%s]\n",
1634 __func__
, te
, handler_name
, location
));
1636 smbd_impersonate_root_after_use(wrap_ev
, private_data
, main_ev
, location
);
1639 static void smbd_impersonate_root_before_immediate_handler(struct tevent_context
*wrap_ev
,
1641 struct tevent_context
*main_ev
,
1642 struct tevent_immediate
*im
,
1643 const char *handler_name
,
1644 const char *location
)
1646 DEBUG(11,("%s: im[%p] handler_name[%s] location[%s]\n",
1647 __func__
, im
, handler_name
, location
));
1649 smbd_impersonate_root_before_use(wrap_ev
, private_data
, main_ev
, location
);
1652 static void smbd_impersonate_root_after_immediate_handler(struct tevent_context
*wrap_ev
,
1654 struct tevent_context
*main_ev
,
1655 struct tevent_immediate
*im
,
1656 const char *handler_name
,
1657 const char *location
)
1659 DEBUG(11,("%s: im[%p] handler_name[%s] location[%s]\n",
1660 __func__
, im
, handler_name
, location
));
1662 smbd_impersonate_root_after_use(wrap_ev
, private_data
, main_ev
, location
);
1665 static void smbd_impersonate_root_before_signal_handler(struct tevent_context
*wrap_ev
,
1667 struct tevent_context
*main_ev
,
1668 struct tevent_signal
*se
,
1672 const char *handler_name
,
1673 const char *location
)
1675 DEBUG(11,("%s: se[%p] signum[%d] count[%d] siginfo[%p] "
1676 "handler_name[%s] location[%s]\n",
1677 __func__
, se
, signum
, count
, siginfo
, handler_name
, location
));
1679 smbd_impersonate_root_before_use(wrap_ev
, private_data
, main_ev
, location
);
1682 static void smbd_impersonate_root_after_signal_handler(struct tevent_context
*wrap_ev
,
1684 struct tevent_context
*main_ev
,
1685 struct tevent_signal
*se
,
1689 const char *handler_name
,
1690 const char *location
)
1692 DEBUG(11,("%s: se[%p] handler_name[%s] location[%s]\n",
1693 __func__
, se
, handler_name
, location
));
1695 smbd_impersonate_root_after_use(wrap_ev
, private_data
, main_ev
, location
);
1698 static const struct tevent_wrapper_ops smbd_impersonate_root_ops
= {
1699 .name
= "smbd_impersonate_root",
1700 .before_use
= smbd_impersonate_root_before_use
,
1701 .after_use
= smbd_impersonate_root_after_use
,
1702 .before_fd_handler
= smbd_impersonate_root_before_fd_handler
,
1703 .after_fd_handler
= smbd_impersonate_root_after_fd_handler
,
1704 .before_timer_handler
= smbd_impersonate_root_before_timer_handler
,
1705 .after_timer_handler
= smbd_impersonate_root_after_timer_handler
,
1706 .before_immediate_handler
= smbd_impersonate_root_before_immediate_handler
,
1707 .after_immediate_handler
= smbd_impersonate_root_after_immediate_handler
,
1708 .before_signal_handler
= smbd_impersonate_root_before_signal_handler
,
1709 .after_signal_handler
= smbd_impersonate_root_after_signal_handler
,
1712 struct tevent_context
*smbd_impersonate_root_create(struct tevent_context
*main_ev
)
1714 struct tevent_context
*ev
= NULL
;
1715 struct smbd_impersonate_root_state
*state
= NULL
;
1717 ev
= tevent_context_wrapper_create(main_ev
,
1719 &smbd_impersonate_root_ops
,
1721 struct smbd_impersonate_root_state
);
1729 struct smbd_impersonate_guest_state
{
1733 static bool smbd_impersonate_guest_before_use(struct tevent_context
*wrap_ev
,
1735 struct tevent_context
*main_ev
,
1736 const char *location
)
1738 DEBUG(11,("%s: wrap_ev[%p] main_ev[%p] location[%s]"
1739 "uid[%ju] gid[%ju]\n",
1740 __func__
, wrap_ev
, main_ev
, location
,
1741 (uintmax_t)geteuid(), (uintmax_t)getegid()));
1743 return become_guest();
1746 static void smbd_impersonate_guest_after_use(struct tevent_context
*wrap_ev
,
1748 struct tevent_context
*main_ev
,
1749 const char *location
)
1753 DEBUG(11,("%s: uid[%ju] gid[%ju] location[%s]\n",
1754 __func__
, (uintmax_t)geteuid(), (uintmax_t)getegid(),
1758 static void smbd_impersonate_guest_before_fd_handler(struct tevent_context
*wrap_ev
,
1760 struct tevent_context
*main_ev
,
1761 struct tevent_fd
*fde
,
1763 const char *handler_name
,
1764 const char *location
)
1768 DEBUG(11,("%s: fde[%p] flags[%ju] handler_name[%s] location[%s]\n",
1769 __func__
, fde
, (uintmax_t)flags
, handler_name
, location
));
1771 ok
= smbd_impersonate_guest_before_use(wrap_ev
, private_data
,
1774 smb_panic("smbd_impersonate_guest_before_use() - failed");
1779 static void smbd_impersonate_guest_after_fd_handler(struct tevent_context
*wrap_ev
,
1781 struct tevent_context
*main_ev
,
1782 struct tevent_fd
*fde
,
1784 const char *handler_name
,
1785 const char *location
)
1787 DEBUG(11,("%s: fde[%p] handler_name[%s] location[%s]\n",
1788 __func__
, fde
, handler_name
, location
));
1790 smbd_impersonate_guest_after_use(wrap_ev
, private_data
, main_ev
, location
);
1793 static void smbd_impersonate_guest_before_timer_handler(struct tevent_context
*wrap_ev
,
1795 struct tevent_context
*main_ev
,
1796 struct tevent_timer
*te
,
1797 struct timeval requested_time
,
1798 struct timeval trigger_time
,
1799 const char *handler_name
,
1800 const char *location
)
1803 struct timeval_buf requested_buf
;
1804 struct timeval_buf trigger_buf
;
1806 DEBUG(11,("%s: te[%p] requested_time[%s] trigger_time[%s] "
1807 "handler_name[%s] location[%s]\n",
1809 timeval_str_buf(&requested_time
, true, true, &requested_buf
),
1810 timeval_str_buf(&trigger_time
, true, true, &trigger_buf
),
1811 handler_name
, location
));
1813 ok
= smbd_impersonate_guest_before_use(wrap_ev
, private_data
,
1816 smb_panic("smbd_impersonate_guest_before_use() - failed");
1821 static void smbd_impersonate_guest_after_timer_handler(struct tevent_context
*wrap_ev
,
1823 struct tevent_context
*main_ev
,
1824 struct tevent_timer
*te
,
1825 struct timeval requested_time
,
1826 struct timeval trigger_time
,
1827 const char *handler_name
,
1828 const char *location
)
1830 DEBUG(11,("%s: te[%p] handler_name[%s] location[%s]\n",
1831 __func__
, te
, handler_name
, location
));
1833 smbd_impersonate_guest_after_use(wrap_ev
, private_data
, main_ev
, location
);
1836 static void smbd_impersonate_guest_before_immediate_handler(struct tevent_context
*wrap_ev
,
1838 struct tevent_context
*main_ev
,
1839 struct tevent_immediate
*im
,
1840 const char *handler_name
,
1841 const char *location
)
1845 DEBUG(11,("%s: im[%p] handler_name[%s] location[%s]\n",
1846 __func__
, im
, handler_name
, location
));
1848 ok
= smbd_impersonate_guest_before_use(wrap_ev
, private_data
,
1851 smb_panic("smbd_impersonate_guest_before_use() - failed");
1856 static void smbd_impersonate_guest_after_immediate_handler(struct tevent_context
*wrap_ev
,
1858 struct tevent_context
*main_ev
,
1859 struct tevent_immediate
*im
,
1860 const char *handler_name
,
1861 const char *location
)
1863 DEBUG(11,("%s: im[%p] handler_name[%s] location[%s]\n",
1864 __func__
, im
, handler_name
, location
));
1866 smbd_impersonate_guest_after_use(wrap_ev
, private_data
, main_ev
, location
);
1869 static void smbd_impersonate_guest_before_signal_handler(struct tevent_context
*wrap_ev
,
1871 struct tevent_context
*main_ev
,
1872 struct tevent_signal
*se
,
1876 const char *handler_name
,
1877 const char *location
)
1881 DEBUG(11,("%s: se[%p] signum[%d] count[%d] siginfo[%p] "
1882 "handler_name[%s] location[%s]\n",
1883 __func__
, se
, signum
, count
, siginfo
, handler_name
, location
));
1885 ok
= smbd_impersonate_guest_before_use(wrap_ev
, private_data
,
1888 smb_panic("smbd_impersonate_guest_before_use() - failed");
1893 static void smbd_impersonate_guest_after_signal_handler(struct tevent_context
*wrap_ev
,
1895 struct tevent_context
*main_ev
,
1896 struct tevent_signal
*se
,
1900 const char *handler_name
,
1901 const char *location
)
1903 DEBUG(11,("%s: se[%p] handler_name[%s] location[%s]\n",
1904 __func__
, se
, handler_name
, location
));
1906 smbd_impersonate_guest_after_use(wrap_ev
, private_data
, main_ev
, location
);
1909 static const struct tevent_wrapper_ops smbd_impersonate_guest_ops
= {
1910 .name
= "smbd_impersonate_guest",
1911 .before_use
= smbd_impersonate_guest_before_use
,
1912 .after_use
= smbd_impersonate_guest_after_use
,
1913 .before_fd_handler
= smbd_impersonate_guest_before_fd_handler
,
1914 .after_fd_handler
= smbd_impersonate_guest_after_fd_handler
,
1915 .before_timer_handler
= smbd_impersonate_guest_before_timer_handler
,
1916 .after_timer_handler
= smbd_impersonate_guest_after_timer_handler
,
1917 .before_immediate_handler
= smbd_impersonate_guest_before_immediate_handler
,
1918 .after_immediate_handler
= smbd_impersonate_guest_after_immediate_handler
,
1919 .before_signal_handler
= smbd_impersonate_guest_before_signal_handler
,
1920 .after_signal_handler
= smbd_impersonate_guest_after_signal_handler
,
1923 struct tevent_context
*smbd_impersonate_guest_create(struct tevent_context
*main_ev
)
1925 struct tevent_context
*ev
= NULL
;
1926 struct smbd_impersonate_guest_state
*state
= NULL
;
1928 ev
= tevent_context_wrapper_create(main_ev
,
1930 &smbd_impersonate_guest_ops
,
1932 struct smbd_impersonate_guest_state
);
1940 struct smbd_impersonate_tp_current_state
{
1941 const void *conn_ptr
;
1942 uint64_t vuid
; /* SMB2 compat */
1943 struct security_unix_token partial_ut
;
1948 static int smbd_impersonate_tp_current_state_destructor(
1949 struct smbd_impersonate_tp_current_state
*state
)
1951 if (state
->saved_cwd_fd
!= -1) {
1952 smb_panic(__location__
);
1958 static bool smbd_impersonate_tp_current_before_job(struct pthreadpool_tevent
*wrap
,
1960 struct pthreadpool_tevent
*main
,
1961 const char *location
)
1963 struct smbd_impersonate_tp_current_state
*state
=
1964 talloc_get_type_abort(private_data
,
1965 struct smbd_impersonate_tp_current_state
);
1967 if (state
->conn_ptr
!= current_user
.conn
) {
1968 smb_panic(__location__
);
1971 if (state
->vuid
!= current_user
.vuid
) {
1972 smb_panic(__location__
);
1975 if (state
->partial_ut
.uid
!= current_user
.ut
.uid
) {
1976 smb_panic(__location__
);
1979 if (state
->partial_ut
.gid
!= current_user
.ut
.gid
) {
1980 smb_panic(__location__
);
1983 if (state
->partial_ut
.ngroups
!= current_user
.ut
.ngroups
) {
1984 smb_panic(__location__
);
1988 * We don't verify the group list, we should have hit
1989 * an assert before. We only want to catch programmer
1992 * We just have a sync pool and want to make sure
1993 * we're already in the correct state.
1995 * So we don't do any active impersonation.
1999 * we may need to remember the current working directory
2000 * and later restore it in the after_job hook.
2002 if (state
->chdir_safe
) {
2003 int open_flags
= O_RDONLY
;
2007 open_flags
|= O_DIRECTORY
;
2010 open_flags
|= O_CLOEXEC
;
2013 state
->saved_cwd_fd
= open(".", open_flags
);
2014 if (state
->saved_cwd_fd
== -1) {
2015 DBG_ERR("unable to open '.' with open_flags[0x%x] - %s\n",
2016 open_flags
, strerror(errno
));
2017 smb_panic("smbd_impersonate_tp_current_before_job: "
2018 "unable to open cwd '.'");
2021 ok
= smb_set_close_on_exec(state
->saved_cwd_fd
);
2028 static bool smbd_impersonate_tp_current_after_job(struct pthreadpool_tevent
*wrap
,
2030 struct pthreadpool_tevent
*main
,
2031 const char *location
)
2033 struct smbd_impersonate_tp_current_state
*state
=
2034 talloc_get_type_abort(private_data
,
2035 struct smbd_impersonate_tp_current_state
);
2039 * There's no impersonation to revert.
2041 * But we may need to reset the current working directory.
2043 if (state
->saved_cwd_fd
== -1) {
2047 ret
= fchdir(state
->saved_cwd_fd
);
2049 DBG_ERR("unable to fchdir to the original directory - %s\n",
2051 smb_panic("smbd_impersonate_tp_current_after_job: "
2052 "unable restore cwd with fchdir.");
2056 close(state
->saved_cwd_fd
);
2057 state
->saved_cwd_fd
= -1;
2062 static const struct pthreadpool_tevent_wrapper_ops smbd_impersonate_tp_current_ops
= {
2063 .name
= "smbd_impersonate_tp_current",
2064 .before_job
= smbd_impersonate_tp_current_before_job
,
2065 .after_job
= smbd_impersonate_tp_current_after_job
,
2068 struct pthreadpool_tevent
*smbd_impersonate_tp_current_create(
2069 TALLOC_CTX
*mem_ctx
,
2070 struct pthreadpool_tevent
*sync_tp
,
2071 struct connection_struct
*conn
,
2072 uint64_t vuid
, bool chdir_safe
,
2073 const struct security_unix_token
*unix_token
)
2075 struct pthreadpool_tevent
*wrap_tp
= NULL
;
2076 struct smbd_impersonate_tp_current_state
*state
= NULL
;
2079 max_threads
= pthreadpool_tevent_max_threads(sync_tp
);
2080 SMB_ASSERT(max_threads
== 0);
2083 * We have a fake threadpool without real threads.
2084 * So we just provide a a wrapper that asserts that
2085 * we are already in the required impersonation state.
2088 wrap_tp
= pthreadpool_tevent_wrapper_create(sync_tp
,
2090 &smbd_impersonate_tp_current_ops
,
2092 struct smbd_impersonate_tp_current_state
);
2093 if (wrap_tp
== NULL
) {
2097 state
->conn_ptr
= conn
;
2099 state
->partial_ut
= *unix_token
;
2100 state
->partial_ut
.groups
= NULL
;
2101 state
->chdir_safe
= chdir_safe
;
2102 state
->saved_cwd_fd
= -1;
2105 pthreadpool_tevent_force_per_thread_cwd(wrap_tp
, state
);
2108 talloc_set_destructor(state
, smbd_impersonate_tp_current_state_destructor
);
2113 struct smbd_impersonate_tp_sess_state
{
2114 const struct security_unix_token
*unix_token
;
2117 static bool smbd_impersonate_tp_sess_before_job(struct pthreadpool_tevent
*wrap
,
2119 struct pthreadpool_tevent
*main
,
2120 const char *location
)
2122 struct smbd_impersonate_tp_sess_state
*state
=
2123 talloc_get_type_abort(private_data
,
2124 struct smbd_impersonate_tp_sess_state
);
2127 /* Become the correct credential on this thread. */
2128 ret
= set_thread_credentials(state
->unix_token
->uid
,
2129 state
->unix_token
->gid
,
2130 (size_t)state
->unix_token
->ngroups
,
2131 state
->unix_token
->groups
);
2139 static bool smbd_impersonate_tp_sess_after_job(struct pthreadpool_tevent
*wrap
,
2141 struct pthreadpool_tevent
*main
,
2142 const char *location
)
2145 * We skip the 'unbecome' here, if the following
2146 * job cares, it already called set_thread_credentials() again.
2148 * fd based jobs on the raw pool, don't really care...
2153 static const struct pthreadpool_tevent_wrapper_ops smbd_impersonate_tp_sess_ops
= {
2154 .name
= "smbd_impersonate_tp_sess",
2155 .before_job
= smbd_impersonate_tp_sess_before_job
,
2156 .after_job
= smbd_impersonate_tp_sess_after_job
,
2159 static struct pthreadpool_tevent
*smbd_impersonate_tp_sess_create(
2160 TALLOC_CTX
*mem_ctx
,
2161 struct pthreadpool_tevent
*main_tp
,
2162 struct auth_session_info
*session_info
)
2164 struct pthreadpool_tevent
*wrap_tp
= NULL
;
2165 struct smbd_impersonate_tp_sess_state
*state
= NULL
;
2168 max_threads
= pthreadpool_tevent_max_threads(main_tp
);
2169 SMB_ASSERT(max_threads
> 0);
2171 wrap_tp
= pthreadpool_tevent_wrapper_create(main_tp
,
2173 &smbd_impersonate_tp_sess_ops
,
2175 struct smbd_impersonate_tp_sess_state
);
2176 if (wrap_tp
== NULL
) {
2180 state
->unix_token
= copy_unix_token(state
, session_info
->unix_token
);
2181 if (state
->unix_token
== NULL
) {
2182 int saved_errno
= errno
;
2183 TALLOC_FREE(wrap_tp
);
2184 errno
= saved_errno
;
2191 struct smbd_impersonate_tp_become_state
{
2192 void (*become_fn
)(void);
2193 void (*unbecome_fn
)(void);
2198 static int smbd_impersonate_tp_become_state_destructor(
2199 struct smbd_impersonate_tp_become_state
*state
)
2201 if (state
->saved_cwd_fd
!= -1) {
2202 smb_panic(__location__
);
2209 static bool smbd_impersonate_tp_become_before_job(struct pthreadpool_tevent
*wrap
,
2211 struct pthreadpool_tevent
*main
,
2212 const char *location
)
2214 struct smbd_impersonate_tp_become_state
*state
=
2215 talloc_get_type_abort(private_data
,
2216 struct smbd_impersonate_tp_become_state
);
2219 * we may need to remember the current working directory
2220 * and later restore it in the after_job hook.
2222 if (state
->chdir_safe
) {
2223 int open_flags
= O_RDONLY
;
2227 open_flags
|= O_DIRECTORY
;
2230 open_flags
|= O_CLOEXEC
;
2233 state
->saved_cwd_fd
= open(".", open_flags
);
2234 if (state
->saved_cwd_fd
== -1) {
2235 DBG_ERR("unable to open '.' with open_flags[0x%x] - %s\n",
2236 open_flags
, strerror(errno
));
2237 smb_panic("smbd_impersonate_tp_current_before_job: "
2238 "unable to open cwd '.'");
2241 ok
= smb_set_close_on_exec(state
->saved_cwd_fd
);
2246 * The function should abort on error...
2253 static bool smbd_impersonate_tp_become_after_job(struct pthreadpool_tevent
*wrap
,
2255 struct pthreadpool_tevent
*main
,
2256 const char *location
)
2258 struct smbd_impersonate_tp_become_state
*state
=
2259 talloc_get_type_abort(private_data
,
2260 struct smbd_impersonate_tp_become_state
);
2264 * The function should abort on error...
2266 state
->unbecome_fn();
2269 * There's no impersonation to revert.
2271 * But we may need to reset the current working directory.
2273 if (state
->saved_cwd_fd
== -1) {
2277 ret
= fchdir(state
->saved_cwd_fd
);
2279 DBG_ERR("unable to fchdir to the original directory - %s\n",
2281 smb_panic("smbd_impersonate_tp_current_after_job: "
2282 "unable restore cwd with fchdir.");
2286 close(state
->saved_cwd_fd
);
2287 state
->saved_cwd_fd
= -1;
2292 static const struct pthreadpool_tevent_wrapper_ops smbd_impersonate_tp_become_ops
= {
2293 .name
= "smbd_impersonate_tp_become",
2294 .before_job
= smbd_impersonate_tp_become_before_job
,
2295 .after_job
= smbd_impersonate_tp_become_after_job
,
2298 struct pthreadpool_tevent
*smbd_impersonate_tp_become_create(
2299 TALLOC_CTX
*mem_ctx
,
2300 struct pthreadpool_tevent
*sync_tp
,
2302 void (*become_fn
)(void),
2303 void (*unbecome_fn
)(void))
2305 struct pthreadpool_tevent
*wrap_tp
= NULL
;
2306 struct smbd_impersonate_tp_become_state
*state
= NULL
;
2309 max_threads
= pthreadpool_tevent_max_threads(sync_tp
);
2310 SMB_ASSERT(max_threads
== 0);
2313 * We have a fake threadpool without real threads.
2314 * So we just provide a a wrapper that asserts that
2315 * we are already in the required impersonation state.
2318 wrap_tp
= pthreadpool_tevent_wrapper_create(sync_tp
,
2320 &smbd_impersonate_tp_become_ops
,
2322 struct smbd_impersonate_tp_become_state
);
2323 if (wrap_tp
== NULL
) {
2327 state
->become_fn
= become_fn
;
2328 state
->unbecome_fn
= unbecome_fn
;
2329 state
->chdir_safe
= chdir_safe
;
2330 state
->saved_cwd_fd
= -1;
2333 pthreadpool_tevent_force_per_thread_cwd(wrap_tp
, state
);
2336 talloc_set_destructor(state
, smbd_impersonate_tp_become_state_destructor
);
2341 struct smbd_impersonate_tp_root_state
{
2342 const struct security_unix_token
*fallback_token
;
2345 static bool smbd_impersonate_tp_root_before_job(struct pthreadpool_tevent
*wrap
,
2347 struct pthreadpool_tevent
*main
,
2348 const char *location
)
2353 * Become root in this thread.
2355 ret
= set_thread_credentials(0, 0, 0, NULL
);
2363 static bool smbd_impersonate_tp_root_after_job(struct pthreadpool_tevent
*wrap
,
2365 struct pthreadpool_tevent
*main
,
2366 const char *location
)
2368 struct smbd_impersonate_tp_root_state
*state
=
2369 talloc_get_type_abort(private_data
,
2370 struct smbd_impersonate_tp_root_state
);
2374 * Move to a non root token again.
2375 * We just use the one of the user_ev_ctx.
2377 * The main goal is that we don't leave
2378 * a thread arround with a root token.
2380 ret
= set_thread_credentials(state
->fallback_token
->uid
,
2381 state
->fallback_token
->gid
,
2382 (size_t)state
->fallback_token
->ngroups
,
2383 state
->fallback_token
->groups
);
2391 static const struct pthreadpool_tevent_wrapper_ops smbd_impersonate_tp_root_ops
= {
2392 .name
= "smbd_impersonate_tp_root",
2393 .before_job
= smbd_impersonate_tp_root_before_job
,
2394 .after_job
= smbd_impersonate_tp_root_after_job
,
2397 static struct pthreadpool_tevent
*smbd_impersonate_tp_root_create(
2398 TALLOC_CTX
*mem_ctx
,
2399 struct pthreadpool_tevent
*main_tp
,
2401 const struct security_unix_token
*fallback_token
)
2403 struct pthreadpool_tevent
*wrap_tp
= NULL
;
2404 struct smbd_impersonate_tp_root_state
*state
= NULL
;
2407 max_threads
= pthreadpool_tevent_max_threads(main_tp
);
2408 SMB_ASSERT(max_threads
> 0);
2410 wrap_tp
= pthreadpool_tevent_wrapper_create(main_tp
,
2412 &smbd_impersonate_tp_root_ops
,
2414 struct smbd_impersonate_tp_root_state
);
2415 if (wrap_tp
== NULL
) {
2419 state
->fallback_token
= copy_unix_token(state
, fallback_token
);
2420 if (state
->fallback_token
== NULL
) {
2421 int saved_errno
= errno
;
2422 TALLOC_FREE(wrap_tp
);
2423 errno
= saved_errno
;
2430 static struct smb_vfs_ev_glue
*smbd_impersonate_user_ev_glue_create(
2431 struct connection_struct
*conn
,
2433 struct auth_session_info
*session_info
)
2435 TALLOC_CTX
*frame
= talloc_stackframe();
2436 struct smb_vfs_ev_glue
*user_vfs_evg
= NULL
;
2437 struct tevent_context
*user_ev_ctx
= NULL
;
2438 struct pthreadpool_tevent
*user_tp_fd_safe
= NULL
;
2439 struct pthreadpool_tevent
*user_tp_path_safe
= NULL
;
2440 bool user_tp_path_sync
= true;
2441 struct pthreadpool_tevent
*user_tp_chdir_safe
= NULL
;
2442 bool user_tp_chdir_sync
= true;
2443 struct pthreadpool_tevent
*root_tp_fd_safe
= NULL
;
2444 struct pthreadpool_tevent
*root_tp_path_safe
= NULL
;
2445 bool root_tp_path_sync
= true;
2446 struct pthreadpool_tevent
*root_tp_chdir_safe
= NULL
;
2447 bool root_tp_chdir_sync
= true;
2450 if (vuid
== UID_FIELD_INVALID
) {
2451 user_ev_ctx
= smbd_impersonate_conn_sess_create(
2452 conn
->sconn
->raw_ev_ctx
, conn
, session_info
);
2453 if (user_ev_ctx
== NULL
) {
2458 user_ev_ctx
= smbd_impersonate_conn_vuid_create(
2459 conn
->sconn
->raw_ev_ctx
, conn
, vuid
);
2460 if (user_ev_ctx
== NULL
) {
2465 SMB_ASSERT(talloc_reparent(conn
, frame
, user_ev_ctx
));
2467 #ifdef HAVE_LINUX_THREAD_CREDENTIALS
2468 user_tp_path_sync
= lp_parm_bool(SNUM(conn
),
2470 "force sync user path safe threadpool",
2472 user_tp_chdir_sync
= lp_parm_bool(SNUM(conn
),
2474 "force sync user chdir safe threadpool",
2476 root_tp_path_sync
= lp_parm_bool(SNUM(conn
),
2478 "force sync root path safe threadpool",
2480 root_tp_chdir_sync
= lp_parm_bool(SNUM(conn
),
2482 "force sync root chdir safe threadpool",
2486 max_threads
= pthreadpool_tevent_max_threads(conn
->sconn
->raw_thread_pool
);
2487 if (max_threads
== 0) {
2489 * We don't have real threads, so we need to force
2490 * the sync versions...
2492 user_tp_path_sync
= true;
2493 user_tp_chdir_sync
= true;
2494 root_tp_path_sync
= true;
2495 root_tp_chdir_sync
= true;
2499 * fd_safe is easy :-)
2501 user_tp_fd_safe
= conn
->sconn
->raw_thread_pool
;
2502 root_tp_fd_safe
= conn
->sconn
->raw_thread_pool
;
2504 if (user_tp_path_sync
) {
2506 * We don't have support for per thread credentials,
2507 * so we just provide a sync thread pool with a wrapper
2508 * that asserts that we are already in the required
2509 * impersonation state.
2511 user_tp_path_safe
= smbd_impersonate_tp_current_create(conn
,
2512 conn
->sconn
->sync_thread_pool
,
2515 false, /* chdir_safe */
2516 session_info
->unix_token
);
2517 if (user_tp_path_safe
== NULL
) {
2522 user_tp_path_safe
= smbd_impersonate_tp_sess_create(conn
,
2523 conn
->sconn
->raw_thread_pool
,
2525 if (user_tp_path_safe
== NULL
) {
2530 SMB_ASSERT(talloc_reparent(conn
, frame
, user_tp_path_safe
));
2532 if (pthreadpool_tevent_per_thread_cwd(user_tp_path_safe
)) {
2533 user_tp_chdir_safe
= user_tp_path_safe
;
2535 user_tp_chdir_sync
= true;
2538 if (user_tp_chdir_sync
) {
2540 * We don't have support for per thread credentials,
2541 * so we just provide a sync thread pool with a wrapper
2542 * that asserts that we are already in the required
2543 * impersonation state.
2545 * And it needs to cleanup after [f]chdir() within
2548 user_tp_chdir_safe
= smbd_impersonate_tp_current_create(conn
,
2549 conn
->sconn
->sync_thread_pool
,
2552 true, /* chdir_safe */
2553 session_info
->unix_token
);
2554 if (user_tp_chdir_safe
== NULL
) {
2558 SMB_ASSERT(talloc_reparent(conn
, frame
, user_tp_chdir_safe
));
2560 SMB_ASSERT(user_tp_chdir_safe
!= NULL
);
2563 if (root_tp_path_sync
) {
2565 * We don't have support for per thread credentials,
2566 * so we just provide a sync thread pool with a wrapper
2567 * that wrapps the job in become_root()/unbecome_root().
2569 root_tp_path_safe
= smbd_impersonate_tp_become_create(conn
,
2570 conn
->sconn
->sync_thread_pool
,
2571 false, /* chdir_safe */
2574 if (root_tp_path_safe
== NULL
) {
2579 root_tp_path_safe
= smbd_impersonate_tp_root_create(conn
,
2580 conn
->sconn
->raw_thread_pool
,
2582 session_info
->unix_token
);
2583 if (root_tp_path_safe
== NULL
) {
2588 SMB_ASSERT(talloc_reparent(conn
, frame
, root_tp_path_safe
));
2590 if (pthreadpool_tevent_per_thread_cwd(root_tp_path_safe
)) {
2591 root_tp_chdir_safe
= root_tp_path_safe
;
2593 root_tp_chdir_sync
= true;
2596 if (root_tp_chdir_sync
) {
2598 * We don't have support for per thread credentials,
2599 * so we just provide a sync thread pool with a wrapper
2600 * that wrapps the job in become_root()/unbecome_root().
2602 * And it needs to cleanup after [f]chdir() within
2605 root_tp_chdir_safe
= smbd_impersonate_tp_become_create(conn
,
2606 conn
->sconn
->sync_thread_pool
,
2607 true, /* chdir_safe */
2610 if (root_tp_chdir_safe
== NULL
) {
2614 SMB_ASSERT(talloc_reparent(conn
, frame
, root_tp_chdir_safe
));
2616 SMB_ASSERT(root_tp_chdir_safe
!= NULL
);
2619 user_vfs_evg
= smb_vfs_ev_glue_create(conn
,
2624 conn
->sconn
->root_ev_ctx
,
2627 root_tp_chdir_safe
);
2628 if (user_vfs_evg
== NULL
) {
2634 * Make sure everything is a talloc child of user_vfs_evg
2636 SMB_ASSERT(talloc_reparent(frame
, user_vfs_evg
, user_ev_ctx
));
2637 SMB_ASSERT(talloc_reparent(frame
, user_vfs_evg
, user_tp_path_safe
));
2638 if (user_tp_path_safe
!= user_tp_chdir_safe
) {
2639 SMB_ASSERT(talloc_reparent(frame
, user_vfs_evg
, user_tp_chdir_safe
));
2641 SMB_ASSERT(talloc_reparent(frame
, user_vfs_evg
, root_tp_path_safe
));
2642 if (root_tp_path_safe
!= root_tp_chdir_safe
) {
2643 SMB_ASSERT(talloc_reparent(frame
, user_vfs_evg
, root_tp_chdir_safe
));
2647 return user_vfs_evg
;