Revert "smbd: implement smbd_impersonate_{conn_vuid,conn_sess,root,guest}_create...
[samba.git] / source3 / smbd / uid.c
1 /* 
2    Unix SMB/CIFS implementation.
3    uid/user handling
4    Copyright (C) Andrew Tridgell 1992-1998
5
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.
10
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.
15
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/>.
18 */
19
20 #include "includes.h"
21 #include "system/passwd.h"
22 #include "smbd/smbd.h"
23 #include "smbd/globals.h"
24 #include "../librpc/gen_ndr/netlogon.h"
25 #include "libcli/security/security.h"
26 #include "passdb/lookup_sid.h"
27 #include "auth.h"
28 #include "../auth/auth_util.h"
29 #include "lib/util/time_basic.h"
30
31 struct smbd_impersonate_debug_state {
32         int dbg_lvl;
33         const char *name;
34 };
35
36 static bool smbd_impersonate_debug_before_use(struct tevent_context *wrap_ev,
37                                               void *private_data,
38                                               struct tevent_context *main_ev,
39                                               const char *location)
40 {
41         struct smbd_impersonate_debug_state *state =
42                 (struct smbd_impersonate_debug_state *)private_data;
43
44         DEBUG(state->dbg_lvl, (
45               "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] location[%s]\n",
46               __func__, state->name, wrap_ev, state, main_ev, location));
47
48         return true;
49 }
50
51 static void smbd_impersonate_debug_after_use(struct tevent_context *wrap_ev,
52                                              void *private_data,
53                                              struct tevent_context *main_ev,
54                                              const char *location)
55 {
56         struct smbd_impersonate_debug_state *state =
57                 (struct smbd_impersonate_debug_state *)private_data;
58
59         DEBUG(state->dbg_lvl, (
60               "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] location[%s]\n",
61               __func__, state->name, wrap_ev, state, main_ev, location));
62 }
63
64 static void smbd_impersonate_debug_before_fd_handler(struct tevent_context *wrap_ev,
65                                                 void *private_data,
66                                                 struct tevent_context *main_ev,
67                                                 struct tevent_fd *fde,
68                                                 uint16_t flags,
69                                                 const char *handler_name,
70                                                 const char *location)
71 {
72         struct smbd_impersonate_debug_state *state =
73                 (struct smbd_impersonate_debug_state *)private_data;
74
75         DEBUG(state->dbg_lvl, (
76               "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] "
77               "fde[%p] flags[0x%X] handler_name[%s] location[%s]\n",
78               __func__, state->name, wrap_ev, state, main_ev,
79               fde, flags, handler_name, location));
80 }
81
82 static void smbd_impersonate_debug_after_fd_handler(struct tevent_context *wrap_ev,
83                                                 void *private_data,
84                                                 struct tevent_context *main_ev,
85                                                 struct tevent_fd *fde,
86                                                 uint16_t flags,
87                                                 const char *handler_name,
88                                                 const char *location)
89 {
90         struct smbd_impersonate_debug_state *state =
91                 (struct smbd_impersonate_debug_state *)private_data;
92
93         DEBUG(state->dbg_lvl, (
94               "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] "
95               "fde[%p] flags[0x%X] handler_name[%s] location[%s]\n",
96               __func__, state->name, wrap_ev, state, main_ev,
97               fde, flags, handler_name, location));
98 }
99
100 static void smbd_impersonate_debug_before_timer_handler(struct tevent_context *wrap_ev,
101                                                 void *private_data,
102                                                 struct tevent_context *main_ev,
103                                                 struct tevent_timer *te,
104                                                 struct timeval requested_time,
105                                                 struct timeval trigger_time,
106                                                 const char *handler_name,
107                                                 const char *location)
108 {
109         struct smbd_impersonate_debug_state *state =
110                 (struct smbd_impersonate_debug_state *)private_data;
111         struct timeval_buf requested_buf;
112         struct timeval_buf trigger_buf;
113
114         DEBUG(state->dbg_lvl, (
115               "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] "
116               "te[%p] requested_time[%s] trigger_time[%s] handler_name[%s] location[%s]\n",
117               __func__, state->name, wrap_ev, state, main_ev, te,
118               timeval_str_buf(&requested_time, true, true, &requested_buf),
119               timeval_str_buf(&trigger_time, true, true, &trigger_buf),
120               handler_name, location));
121 }
122
123 static void smbd_impersonate_debug_after_timer_handler(struct tevent_context *wrap_ev,
124                                                 void *private_data,
125                                                 struct tevent_context *main_ev,
126                                                 struct tevent_timer *te,
127                                                 struct timeval requested_time,
128                                                 struct timeval trigger_time,
129                                                 const char *handler_name,
130                                                 const char *location)
131 {
132         struct smbd_impersonate_debug_state *state =
133                 (struct smbd_impersonate_debug_state *)private_data;
134         struct timeval_buf requested_buf;
135         struct timeval_buf trigger_buf;
136
137         DEBUG(state->dbg_lvl, (
138               "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] "
139               "te[%p] requested_time[%s] trigger_time[%s] handler_name[%s] location[%s]\n",
140               __func__, state->name, wrap_ev, state, main_ev, te,
141               timeval_str_buf(&requested_time, true, true, &requested_buf),
142               timeval_str_buf(&trigger_time, true, true, &trigger_buf),
143               handler_name, location));
144 }
145
146 static void smbd_impersonate_debug_before_immediate_handler(struct tevent_context *wrap_ev,
147                                                 void *private_data,
148                                                 struct tevent_context *main_ev,
149                                                 struct tevent_immediate *im,
150                                                 const char *handler_name,
151                                                 const char *location)
152 {
153         struct smbd_impersonate_debug_state *state =
154                 (struct smbd_impersonate_debug_state *)private_data;
155
156         DEBUG(state->dbg_lvl, (
157               "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] "
158               "im[%p] handler_name[%s] location[%s]\n",
159               __func__, state->name, wrap_ev, state, main_ev,
160               im, handler_name, location));
161 }
162
163 static void smbd_impersonate_debug_after_immediate_handler(struct tevent_context *wrap_ev,
164                                                 void *private_data,
165                                                 struct tevent_context *main_ev,
166                                                 struct tevent_immediate *im,
167                                                 const char *handler_name,
168                                                 const char *location)
169 {
170         struct smbd_impersonate_debug_state *state =
171                 (struct smbd_impersonate_debug_state *)private_data;
172
173         DEBUG(state->dbg_lvl, (
174               "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] "
175               "im[%p] handler_name[%s] location[%s]\n",
176               __func__, state->name, wrap_ev, state, main_ev,
177               im, handler_name, location));
178 }
179
180 static void smbd_impersonate_debug_before_signal_handler(struct tevent_context *wrap_ev,
181                                                 void *private_data,
182                                                 struct tevent_context *main_ev,
183                                                 struct tevent_signal *se,
184                                                 int signum,
185                                                 int count,
186                                                 void *siginfo,
187                                                 const char *handler_name,
188                                                 const char *location)
189 {
190         struct smbd_impersonate_debug_state *state =
191                 (struct smbd_impersonate_debug_state *)private_data;
192
193         DEBUG(state->dbg_lvl, (
194               "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] "
195               "se[%p] signum[%d] count[%d] siginfo[%p] handler_name[%s] location[%s]\n",
196               __func__, state->name, wrap_ev, state, main_ev,
197               se, signum, count, siginfo, handler_name, location));
198 }
199
200 static void smbd_impersonate_debug_after_signal_handler(struct tevent_context *wrap_ev,
201                                                 void *private_data,
202                                                 struct tevent_context *main_ev,
203                                                 struct tevent_signal *se,
204                                                 int signum,
205                                                 int count,
206                                                 void *siginfo,
207                                                 const char *handler_name,
208                                                 const char *location)
209 {
210         struct smbd_impersonate_debug_state *state =
211                 (struct smbd_impersonate_debug_state *)private_data;
212
213         DEBUG(state->dbg_lvl, (
214               "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] "
215               "se[%p] signum[%d] count[%d] siginfo[%p] handler_name[%s] location[%s]\n",
216               __func__, state->name, wrap_ev, state, main_ev,
217               se, signum, count, siginfo, handler_name, location));
218 }
219
220 static const struct tevent_wrapper_ops smbd_impersonate_debug_ops = {
221         .name                           = "smbd_impersonate_debug",
222         .before_use                     = smbd_impersonate_debug_before_use,
223         .after_use                      = smbd_impersonate_debug_after_use,
224         .before_fd_handler              = smbd_impersonate_debug_before_fd_handler,
225         .after_fd_handler               = smbd_impersonate_debug_after_fd_handler,
226         .before_timer_handler           = smbd_impersonate_debug_before_timer_handler,
227         .after_timer_handler            = smbd_impersonate_debug_after_timer_handler,
228         .before_immediate_handler       = smbd_impersonate_debug_before_immediate_handler,
229         .after_immediate_handler        = smbd_impersonate_debug_after_immediate_handler,
230         .before_signal_handler          = smbd_impersonate_debug_before_signal_handler,
231         .after_signal_handler           = smbd_impersonate_debug_after_signal_handler,
232 };
233
234 struct tevent_context *_smbd_impersonate_debug_create(struct tevent_context *main_ev,
235                                                       const char *name,
236                                                       int dbg_lvl,
237                                                       const char *location)
238 {
239         struct tevent_context *wrap_ev = NULL;
240         struct smbd_impersonate_debug_state *state = NULL;
241
242         wrap_ev = tevent_context_wrapper_create(main_ev,
243                                         main_ev,
244                                         &smbd_impersonate_debug_ops,
245                                         &state,
246                                         struct smbd_impersonate_debug_state);
247         if (wrap_ev == NULL) {
248                 return NULL;
249         }
250         state->name = name;
251         state->dbg_lvl = dbg_lvl;
252         DEBUG(state->dbg_lvl, (
253               "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] location[%s]\n",
254               __func__, state->name, wrap_ev, state, main_ev, location));
255
256         return wrap_ev;
257 }
258
259 /* what user is current? */
260 extern struct current_user current_user;
261
262 /****************************************************************************
263  Become the guest user without changing the security context stack.
264 ****************************************************************************/
265
266 bool change_to_guest(void)
267 {
268         struct passwd *pass;
269
270         pass = Get_Pwnam_alloc(talloc_tos(), lp_guest_account());
271         if (!pass) {
272                 return false;
273         }
274
275 #ifdef AIX
276         /* MWW: From AIX FAQ patch to WU-ftpd: call initgroups before 
277            setting IDs */
278         initgroups(pass->pw_name, pass->pw_gid);
279 #endif
280
281         set_sec_ctx(pass->pw_uid, pass->pw_gid, 0, NULL, NULL);
282
283         current_user.conn = NULL;
284         current_user.vuid = UID_FIELD_INVALID;
285         current_user.need_chdir = false;
286         current_user.done_chdir = false;
287
288         TALLOC_FREE(pass);
289
290         return true;
291 }
292
293 /****************************************************************************
294  talloc free the conn->session_info if not used in the vuid cache.
295 ****************************************************************************/
296
297 static void free_conn_session_info_if_unused(connection_struct *conn)
298 {
299         unsigned int i;
300
301         for (i = 0; i < VUID_CACHE_SIZE; i++) {
302                 struct vuid_cache_entry *ent;
303                 ent = &conn->vuid_cache->array[i];
304                 if (ent->vuid != UID_FIELD_INVALID &&
305                                 conn->session_info == ent->session_info) {
306                         return;
307                 }
308         }
309         /* Not used, safe to free. */
310         TALLOC_FREE(conn->user_ev_ctx);
311         TALLOC_FREE(conn->session_info);
312 }
313
314 /****************************************************************************
315   Setup the share access mask for a connection.
316 ****************************************************************************/
317
318 static uint32_t create_share_access_mask(int snum,
319                                 bool readonly_share,
320                                 const struct security_token *token)
321 {
322         uint32_t share_access = 0;
323
324         share_access_check(token,
325                         lp_const_servicename(snum),
326                         MAXIMUM_ALLOWED_ACCESS,
327                         &share_access);
328
329         if (readonly_share) {
330                 share_access &=
331                         ~(SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA |
332                           SEC_FILE_WRITE_EA | SEC_FILE_WRITE_ATTRIBUTE |
333                           SEC_DIR_DELETE_CHILD );
334         }
335
336         if (security_token_has_privilege(token, SEC_PRIV_SECURITY)) {
337                 share_access |= SEC_FLAG_SYSTEM_SECURITY;
338         }
339         if (security_token_has_privilege(token, SEC_PRIV_RESTORE)) {
340                 share_access |= SEC_RIGHTS_PRIV_RESTORE;
341         }
342         if (security_token_has_privilege(token, SEC_PRIV_BACKUP)) {
343                 share_access |= SEC_RIGHTS_PRIV_BACKUP;
344         }
345         if (security_token_has_privilege(token, SEC_PRIV_TAKE_OWNERSHIP)) {
346                 share_access |= SEC_STD_WRITE_OWNER;
347         }
348
349         return share_access;
350 }
351
352 /*******************************************************************
353  Calculate access mask and if this user can access this share.
354 ********************************************************************/
355
356 NTSTATUS check_user_share_access(connection_struct *conn,
357                                 const struct auth_session_info *session_info,
358                                 uint32_t *p_share_access,
359                                 bool *p_readonly_share)
360 {
361         int snum = SNUM(conn);
362         uint32_t share_access = 0;
363         bool readonly_share = false;
364
365         if (!user_ok_token(session_info->unix_info->unix_name,
366                            session_info->info->domain_name,
367                            session_info->security_token, snum)) {
368                 return NT_STATUS_ACCESS_DENIED;
369         }
370
371         readonly_share = is_share_read_only_for_token(
372                 session_info->unix_info->unix_name,
373                 session_info->info->domain_name,
374                 session_info->security_token,
375                 conn);
376
377         share_access = create_share_access_mask(snum,
378                                         readonly_share,
379                                         session_info->security_token);
380
381         if ((share_access & (FILE_READ_DATA|FILE_WRITE_DATA)) == 0) {
382                 /* No access, read or write. */
383                 DBG_NOTICE("user %s connection to %s denied due to share "
384                          "security descriptor.\n",
385                          session_info->unix_info->unix_name,
386                          lp_const_servicename(snum));
387                 return NT_STATUS_ACCESS_DENIED;
388         }
389
390         if (!readonly_share &&
391             !(share_access & FILE_WRITE_DATA)) {
392                 /* smb.conf allows r/w, but the security descriptor denies
393                  * write. Fall back to looking at readonly. */
394                 readonly_share = true;
395                 DBG_INFO("falling back to read-only access-evaluation due to "
396                          "security descriptor\n");
397         }
398
399         *p_share_access = share_access;
400         *p_readonly_share = readonly_share;
401
402         return NT_STATUS_OK;
403 }
404
405 /*******************************************************************
406  Check if a username is OK.
407
408  This sets up conn->session_info with a copy related to this vuser that
409  later code can then mess with.
410 ********************************************************************/
411
412 static bool check_user_ok(connection_struct *conn,
413                         uint64_t vuid,
414                         const struct auth_session_info *session_info,
415                         int snum)
416 {
417         unsigned int i;
418         bool readonly_share = false;
419         bool admin_user = false;
420         struct vuid_cache_entry *ent = NULL;
421         uint32_t share_access = 0;
422         NTSTATUS status;
423
424         for (i=0; i<VUID_CACHE_SIZE; i++) {
425                 ent = &conn->vuid_cache->array[i];
426                 if (ent->vuid == vuid) {
427                         if (vuid == UID_FIELD_INVALID) {
428                                 /*
429                                  * Slow path, we don't care
430                                  * about the array traversal.
431                                 */
432                                 continue;
433                         }
434                         free_conn_session_info_if_unused(conn);
435                         conn->session_info = ent->session_info;
436                         conn->user_ev_ctx = ent->user_ev_ctx;
437                         conn->read_only = ent->read_only;
438                         conn->share_access = ent->share_access;
439                         conn->vuid = ent->vuid;
440                         return(True);
441                 }
442         }
443
444         status = check_user_share_access(conn,
445                                         session_info,
446                                         &share_access,
447                                         &readonly_share);
448         if (!NT_STATUS_IS_OK(status)) {
449                 return false;
450         }
451
452         admin_user = token_contains_name_in_list(
453                 session_info->unix_info->unix_name,
454                 session_info->info->domain_name,
455                 NULL, session_info->security_token, lp_admin_users(snum));
456
457         ent = &conn->vuid_cache->array[conn->vuid_cache->next_entry];
458
459         conn->vuid_cache->next_entry =
460                 (conn->vuid_cache->next_entry + 1) % VUID_CACHE_SIZE;
461
462         TALLOC_FREE(ent->session_info);
463
464         /*
465          * If force_user was set, all session_info's are based on the same
466          * username-based faked one.
467          */
468
469         ent->session_info = copy_session_info(
470                 conn, conn->force_user ? conn->session_info : session_info);
471
472         if (ent->session_info == NULL) {
473                 ent->vuid = UID_FIELD_INVALID;
474                 return false;
475         }
476
477         if (admin_user) {
478                 DEBUG(2,("check_user_ok: user %s is an admin user. "
479                         "Setting uid as %d\n",
480                         ent->session_info->unix_info->unix_name,
481                         sec_initial_uid() ));
482                 ent->session_info->unix_token->uid = sec_initial_uid();
483         }
484
485         if (vuid == UID_FIELD_INVALID) {
486                 ent->user_ev_ctx = smbd_impersonate_conn_sess_create(
487                         conn->sconn->raw_ev_ctx, conn, ent->session_info);
488                 if (ent->user_ev_ctx == NULL) {
489                         TALLOC_FREE(ent->session_info);
490                         ent->vuid = UID_FIELD_INVALID;
491                         return false;
492                 }
493         } else {
494                 ent->user_ev_ctx = smbd_impersonate_conn_vuid_create(
495                         conn->sconn->raw_ev_ctx, conn, vuid);
496                 if (ent->user_ev_ctx == NULL) {
497                         TALLOC_FREE(ent->session_info);
498                         ent->vuid = UID_FIELD_INVALID;
499                         return false;
500                 }
501         }
502
503         /*
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.
507          */
508
509         ent->vuid = vuid;
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_ev_ctx = ent->user_ev_ctx;
516         if (vuid == UID_FIELD_INVALID) {
517                 /*
518                  * Not strictly needed, just make it really
519                  * clear this entry is actually an unused one.
520                  */
521                 ent->read_only = false;
522                 ent->share_access = 0;
523                 ent->session_info = NULL;
524                 ent->user_ev_ctx = NULL;
525         }
526
527         conn->read_only = readonly_share;
528         conn->share_access = share_access;
529
530         return(True);
531 }
532
533 /****************************************************************************
534  Become the user of a connection number without changing the security context
535  stack, but modify the current_user entries.
536 ****************************************************************************/
537
538 static bool change_to_user_internal(connection_struct *conn,
539                                     const struct auth_session_info *session_info,
540                                     uint64_t vuid)
541 {
542         int snum;
543         gid_t gid;
544         uid_t uid;
545         char group_c;
546         int num_groups = 0;
547         gid_t *group_list = NULL;
548         bool ok;
549
550         if ((current_user.conn == conn) &&
551             (current_user.vuid == vuid) &&
552             (current_user.need_chdir == conn->tcon_done) &&
553             (current_user.ut.uid == session_info->unix_token->uid))
554         {
555                 DBG_INFO("Skipping user change - already user\n");
556                 return true;
557         }
558
559         set_current_user_info(session_info->unix_info->sanitized_username,
560                               session_info->unix_info->unix_name,
561                               session_info->info->domain_name);
562
563         snum = SNUM(conn);
564
565         ok = check_user_ok(conn, vuid, session_info, snum);
566         if (!ok) {
567                 DBG_WARNING("SMB user %s (unix user %s) "
568                          "not permitted access to share %s.\n",
569                          session_info->unix_info->sanitized_username,
570                          session_info->unix_info->unix_name,
571                          lp_const_servicename(snum));
572                 return false;
573         }
574
575         uid = conn->session_info->unix_token->uid;
576         gid = conn->session_info->unix_token->gid;
577         num_groups = conn->session_info->unix_token->ngroups;
578         group_list  = conn->session_info->unix_token->groups;
579
580         /*
581          * See if we should force group for this service. If so this overrides
582          * any group set in the force user code.
583          */
584         if((group_c = *lp_force_group(talloc_tos(), snum))) {
585
586                 SMB_ASSERT(conn->force_group_gid != (gid_t)-1);
587
588                 if (group_c == '+') {
589                         int i;
590
591                         /*
592                          * Only force group if the user is a member of the
593                          * service group. Check the group memberships for this
594                          * user (we already have this) to see if we should force
595                          * the group.
596                          */
597                         for (i = 0; i < num_groups; i++) {
598                                 if (group_list[i] == conn->force_group_gid) {
599                                         conn->session_info->unix_token->gid =
600                                                 conn->force_group_gid;
601                                         gid = conn->force_group_gid;
602                                         gid_to_sid(&conn->session_info->security_token
603                                                    ->sids[1], gid);
604                                         break;
605                                 }
606                         }
607                 } else {
608                         conn->session_info->unix_token->gid = conn->force_group_gid;
609                         gid = conn->force_group_gid;
610                         gid_to_sid(&conn->session_info->security_token->sids[1],
611                                    gid);
612                 }
613         }
614
615         /*Set current_user since we will immediately also call set_sec_ctx() */
616         current_user.ut.ngroups = num_groups;
617         current_user.ut.groups  = group_list;
618
619         set_sec_ctx(uid,
620                     gid,
621                     current_user.ut.ngroups,
622                     current_user.ut.groups,
623                     conn->session_info->security_token);
624
625         current_user.conn = conn;
626         current_user.vuid = vuid;
627         current_user.need_chdir = conn->tcon_done;
628
629         if (current_user.need_chdir) {
630                 ok = chdir_current_service(conn);
631                 if (!ok) {
632                         DBG_ERR("chdir_current_service() failed!\n");
633                         return false;
634                 }
635                 current_user.done_chdir = true;
636         }
637
638         if (CHECK_DEBUGLVL(DBGLVL_INFO)) {
639                 struct smb_filename *cwdfname = vfs_GetWd(talloc_tos(), conn);
640                 if (cwdfname == NULL) {
641                         return false;
642                 }
643                 DBG_INFO("Impersonated user: uid=(%d,%d), gid=(%d,%d), cwd=[%s]\n",
644                          (int)getuid(),
645                          (int)geteuid(),
646                          (int)getgid(),
647                          (int)getegid(),
648                          cwdfname->base_name);
649                 TALLOC_FREE(cwdfname);
650         }
651
652         return true;
653 }
654
655 bool change_to_user(connection_struct *conn, uint64_t vuid)
656 {
657         struct user_struct *vuser;
658         int snum = SNUM(conn);
659
660         if (!conn) {
661                 DEBUG(2,("Connection not open\n"));
662                 return(False);
663         }
664
665         vuser = get_valid_user_struct(conn->sconn, vuid);
666         if (vuser == NULL) {
667                 /* Invalid vuid sent */
668                 DBG_WARNING("Invalid vuid %llu used on share %s.\n",
669                             (unsigned long long)vuid,
670                             lp_const_servicename(snum));
671                 return false;
672         }
673
674         return change_to_user_internal(conn, vuser->session_info, vuid);
675 }
676
677 bool change_to_user_by_fsp(struct files_struct *fsp)
678 {
679         return change_to_user(fsp->conn, fsp->vuid);
680 }
681
682 static bool change_to_user_by_session(connection_struct *conn,
683                                       const struct auth_session_info *session_info)
684 {
685         SMB_ASSERT(conn != NULL);
686         SMB_ASSERT(session_info != NULL);
687
688         return change_to_user_internal(conn, session_info, UID_FIELD_INVALID);
689 }
690
691 /****************************************************************************
692  Go back to being root without changing the security context stack,
693  but modify the current_user entries.
694 ****************************************************************************/
695
696 bool smbd_change_to_root_user(void)
697 {
698         set_root_sec_ctx();
699
700         DEBUG(5,("change_to_root_user: now uid=(%d,%d) gid=(%d,%d)\n",
701                 (int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid()));
702
703         current_user.conn = NULL;
704         current_user.vuid = UID_FIELD_INVALID;
705         current_user.need_chdir = false;
706         current_user.done_chdir = false;
707
708         return(True);
709 }
710
711 /****************************************************************************
712  Become the user of an authenticated connected named pipe.
713  When this is called we are currently running as the connection
714  user. Doesn't modify current_user.
715 ****************************************************************************/
716
717 bool smbd_become_authenticated_pipe_user(struct auth_session_info *session_info)
718 {
719         if (!push_sec_ctx())
720                 return False;
721
722         set_sec_ctx(session_info->unix_token->uid, session_info->unix_token->gid,
723                     session_info->unix_token->ngroups, session_info->unix_token->groups,
724                     session_info->security_token);
725
726         DEBUG(5, ("Impersonated user: uid=(%d,%d), gid=(%d,%d)\n",
727                  (int)getuid(),
728                  (int)geteuid(),
729                  (int)getgid(),
730                  (int)getegid()));
731
732         return True;
733 }
734
735 /****************************************************************************
736  Unbecome the user of an authenticated connected named pipe.
737  When this is called we are running as the authenticated pipe
738  user and need to go back to being the connection user. Doesn't modify
739  current_user.
740 ****************************************************************************/
741
742 bool smbd_unbecome_authenticated_pipe_user(void)
743 {
744         return pop_sec_ctx();
745 }
746
747 /****************************************************************************
748  Utility functions used by become_xxx/unbecome_xxx.
749 ****************************************************************************/
750
751 static void push_conn_ctx(void)
752 {
753         struct conn_ctx *ctx_p;
754         extern userdom_struct current_user_info;
755
756         /* Check we don't overflow our stack */
757
758         if (conn_ctx_stack_ndx == MAX_SEC_CTX_DEPTH) {
759                 DEBUG(0, ("Connection context stack overflow!\n"));
760                 smb_panic("Connection context stack overflow!\n");
761         }
762
763         /* Store previous user context */
764         ctx_p = &conn_ctx_stack[conn_ctx_stack_ndx];
765
766         ctx_p->conn = current_user.conn;
767         ctx_p->vuid = current_user.vuid;
768         ctx_p->need_chdir = current_user.need_chdir;
769         ctx_p->done_chdir = current_user.done_chdir;
770         ctx_p->user_info = current_user_info;
771
772         DEBUG(4, ("push_conn_ctx(%llu) : conn_ctx_stack_ndx = %d\n",
773                 (unsigned long long)ctx_p->vuid, conn_ctx_stack_ndx));
774
775         conn_ctx_stack_ndx++;
776 }
777
778 static void pop_conn_ctx(void)
779 {
780         struct conn_ctx *ctx_p;
781
782         /* Check for stack underflow. */
783
784         if (conn_ctx_stack_ndx == 0) {
785                 DEBUG(0, ("Connection context stack underflow!\n"));
786                 smb_panic("Connection context stack underflow!\n");
787         }
788
789         conn_ctx_stack_ndx--;
790         ctx_p = &conn_ctx_stack[conn_ctx_stack_ndx];
791
792         set_current_user_info(ctx_p->user_info.smb_name,
793                               ctx_p->user_info.unix_name,
794                               ctx_p->user_info.domain);
795
796         /*
797          * Check if the current context did a chdir_current_service()
798          * and restore the cwd_fname of the previous context
799          * if needed.
800          */
801         if (current_user.done_chdir && ctx_p->need_chdir) {
802                 int ret;
803
804                 ret = vfs_ChDir(ctx_p->conn, ctx_p->conn->cwd_fname);
805                 if (ret != 0) {
806                         DBG_ERR("vfs_ChDir() failed!\n");
807                         smb_panic("vfs_ChDir() failed!\n");
808                 }
809         }
810
811         current_user.conn = ctx_p->conn;
812         current_user.vuid = ctx_p->vuid;
813         current_user.need_chdir = ctx_p->need_chdir;
814         current_user.done_chdir = ctx_p->done_chdir;
815
816         *ctx_p = (struct conn_ctx) {
817                 .vuid = UID_FIELD_INVALID,
818         };
819 }
820
821 /****************************************************************************
822  Temporarily become a root user.  Must match with unbecome_root(). Saves and
823  restores the connection context.
824 ****************************************************************************/
825
826 void smbd_become_root(void)
827 {
828          /*
829           * no good way to handle push_sec_ctx() failing without changing
830           * the prototype of become_root()
831           */
832         if (!push_sec_ctx()) {
833                 smb_panic("become_root: push_sec_ctx failed");
834         }
835         push_conn_ctx();
836         set_root_sec_ctx();
837 }
838
839 /* Unbecome the root user */
840
841 void smbd_unbecome_root(void)
842 {
843         pop_sec_ctx();
844         pop_conn_ctx();
845 }
846
847 bool become_guest(void)
848 {
849         bool ok;
850
851         ok = push_sec_ctx();
852         if (!ok) {
853                 return false;
854         }
855
856         push_conn_ctx();
857
858         ok = change_to_guest();
859         if (!ok) {
860                 pop_sec_ctx();
861                 pop_conn_ctx();
862                 return false;
863         }
864
865         return true;
866 }
867
868 void unbecome_guest(void)
869 {
870         pop_sec_ctx();
871         pop_conn_ctx();
872         return;
873 }
874
875 /****************************************************************************
876  Push the current security context then force a change via change_to_user().
877  Saves and restores the connection context.
878 ****************************************************************************/
879
880 bool become_user(connection_struct *conn, uint64_t vuid)
881 {
882         if (!push_sec_ctx())
883                 return False;
884
885         push_conn_ctx();
886
887         if (!change_to_user(conn, vuid)) {
888                 pop_sec_ctx();
889                 pop_conn_ctx();
890                 return False;
891         }
892
893         return True;
894 }
895
896 bool become_user_by_fsp(struct files_struct *fsp)
897 {
898         return become_user(fsp->conn, fsp->vuid);
899 }
900
901 bool become_user_by_session(connection_struct *conn,
902                             const struct auth_session_info *session_info)
903 {
904         if (!push_sec_ctx())
905                 return false;
906
907         push_conn_ctx();
908
909         if (!change_to_user_by_session(conn, session_info)) {
910                 pop_sec_ctx();
911                 pop_conn_ctx();
912                 return false;
913         }
914
915         return true;
916 }
917
918 bool unbecome_user(void)
919 {
920         pop_sec_ctx();
921         pop_conn_ctx();
922         return True;
923 }
924
925 /****************************************************************************
926  Return the current user we are running effectively as on this connection.
927  I'd like to make this return conn->session_info->unix_token->uid, but become_root()
928  doesn't alter this value.
929 ****************************************************************************/
930
931 uid_t get_current_uid(connection_struct *conn)
932 {
933         return current_user.ut.uid;
934 }
935
936 /****************************************************************************
937  Return the current group we are running effectively as on this connection.
938  I'd like to make this return conn->session_info->unix_token->gid, but become_root()
939  doesn't alter this value.
940 ****************************************************************************/
941
942 gid_t get_current_gid(connection_struct *conn)
943 {
944         return current_user.ut.gid;
945 }
946
947 /****************************************************************************
948  Return the UNIX token we are running effectively as on this connection.
949  I'd like to make this return &conn->session_info->unix_token-> but become_root()
950  doesn't alter this value.
951 ****************************************************************************/
952
953 const struct security_unix_token *get_current_utok(connection_struct *conn)
954 {
955         return &current_user.ut;
956 }
957
958 /****************************************************************************
959  Return the Windows token we are running effectively as on this connection.
960  If this is currently a NULL token as we're inside become_root() - a temporary
961  UNIX security override, then we search up the stack for the previous active
962  token.
963 ****************************************************************************/
964
965 const struct security_token *get_current_nttok(connection_struct *conn)
966 {
967         if (current_user.nt_user_token) {
968                 return current_user.nt_user_token;
969         }
970         return sec_ctx_active_token();
971 }
972
973 uint64_t get_current_vuid(connection_struct *conn)
974 {
975         return current_user.vuid;
976 }
977
978 struct tevent_context *smbd_impersonate_conn_vuid_create(
979                                 struct tevent_context *main_ev,
980                                 struct connection_struct *conn,
981                                 uint64_t vuid)
982 {
983         struct tevent_context *wrap_ev = NULL;
984
985         wrap_ev = smbd_impersonate_debug_create(main_ev,
986                                                 "conn_vuid",
987                                                 DBGLVL_DEBUG);
988
989         return wrap_ev;
990 }
991
992 struct tevent_context *smbd_impersonate_conn_sess_create(
993                                 struct tevent_context *main_ev,
994                                 struct connection_struct *conn,
995                                 struct auth_session_info *session_info)
996 {
997         struct tevent_context *wrap_ev = NULL;
998
999         wrap_ev = smbd_impersonate_debug_create(main_ev,
1000                                                 "conn_sess",
1001                                                 DBGLVL_DEBUG);
1002
1003         return wrap_ev;
1004 }
1005
1006 struct tevent_context *smbd_impersonate_root_create(struct tevent_context *main_ev)
1007 {
1008         struct tevent_context *wrap_ev = NULL;
1009
1010         wrap_ev = smbd_impersonate_debug_create(main_ev,
1011                                                 "root",
1012                                                 DBGLVL_DEBUG);
1013
1014         return wrap_ev;
1015 }
1016
1017 struct tevent_context *smbd_impersonate_guest_create(struct tevent_context *main_ev)
1018 {
1019         struct tevent_context *wrap_ev = NULL;
1020
1021         wrap_ev = smbd_impersonate_debug_create(main_ev,
1022                                                 "guest",
1023                                                 DBGLVL_DEBUG);
1024
1025         return wrap_ev;
1026 }