Revert "s3: vfs: add user_vfs_evg to connection_struct"
[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 smbd_impersonate_conn_vuid_state {
979         struct connection_struct *conn;
980         uint64_t vuid;
981 };
982
983 static bool smbd_impersonate_conn_vuid_before_use(
984                 struct tevent_context *wrap_ev,
985                 void *private_data,
986                 struct tevent_context *main_ev,
987                 const char *location)
988 {
989         struct smbd_impersonate_conn_vuid_state *state =
990                 talloc_get_type_abort(private_data,
991                 struct smbd_impersonate_conn_vuid_state);
992         bool ok;
993
994         DEBUG(11,("%s: wrap_ev[%p] main_ev[%p] location[%s]"
995                   "old uid[%ju] old gid[%ju] vuid[%ju] cwd[%s]\n",
996                   __func__, wrap_ev, main_ev, location,
997                   (uintmax_t)geteuid(), (uintmax_t)getegid(),
998                   (uintmax_t)state->vuid, state->conn->cwd_fname->base_name));
999
1000         ok = become_user(state->conn, state->vuid);
1001         if (!ok) {
1002                 smb_panic("smbd_impersonate_conn_vuid_before_use() - failed");
1003                 return false;
1004         }
1005
1006         DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1007                   __func__, state->conn->session_info->unix_info->unix_name,
1008                   (uintmax_t)geteuid(), (uintmax_t)getegid(),
1009                   state->conn->cwd_fname->base_name));
1010
1011         return true;
1012 }
1013
1014 static void smbd_impersonate_conn_vuid_after_use(
1015                 struct tevent_context *wrap_ev,
1016                 void *private_data,
1017                 struct tevent_context *main_ev,
1018                 const char *location)
1019 {
1020         struct smbd_impersonate_conn_vuid_state *state =
1021                 talloc_get_type_abort(private_data,
1022                 struct smbd_impersonate_conn_vuid_state);
1023         bool ok;
1024
1025         DEBUG(11,("%s: deimpersonating[%s] uid[%ju] gid[%ju] cwd[%s] "
1026                   "location[%s]\n",
1027                   __func__, state->conn->session_info->unix_info->unix_name,
1028                   (uintmax_t)geteuid(), (uintmax_t)getegid(),
1029                   state->conn->cwd_fname->base_name, location));
1030
1031         ok = unbecome_user();
1032         if (!ok) {
1033                 smb_panic("smbd_impersonate_conn_vuid_after_use() - failed");
1034                 return;
1035         }
1036
1037         DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1038                   __func__, state->conn->session_info->unix_info->unix_name,
1039                   (uintmax_t)geteuid(), (uintmax_t)getegid(),
1040                   state->conn->cwd_fname->base_name));
1041 }
1042
1043 static void smbd_impersonate_conn_vuid_before_fd_handler(
1044                 struct tevent_context *wrap_ev,
1045                 void *private_data,
1046                 struct tevent_context *main_ev,
1047                 struct tevent_fd *fde,
1048                 uint16_t flags,
1049                 const char *handler_name,
1050                 const char *location)
1051 {
1052         struct smbd_impersonate_conn_vuid_state *state = talloc_get_type_abort(
1053                 private_data, struct smbd_impersonate_conn_vuid_state);
1054         bool ok;
1055
1056         DEBUG(11,("%s: fde[%p] flags[%ju] handler_name[%s] location[%s]\n",
1057                   __func__, fde, (uintmax_t)flags, handler_name, location));
1058
1059         ok = change_to_user(state->conn, state->vuid);
1060         if (!ok) {
1061                 smb_panic("smbd_impersonate_conn_vuid_before_use() - failed");
1062                 return;
1063         }
1064
1065         DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1066                   __func__, state->conn->session_info->unix_info->unix_name,
1067                   (uintmax_t)geteuid(), (uintmax_t)getegid(),
1068                   state->conn->cwd_fname->base_name));
1069 }
1070
1071 static void smbd_impersonate_conn_vuid_after_fd_handler(
1072                 struct tevent_context *wrap_ev,
1073                 void *private_data,
1074                 struct tevent_context *main_ev,
1075                 struct tevent_fd *fde,
1076                 uint16_t flags,
1077                 const char *handler_name,
1078                 const char *location)
1079 {
1080         DEBUG(11,("%s: fde[%p] handler_name[%s] location[%s]\n",
1081                   __func__, fde, handler_name, location));
1082
1083         /* be lazy and defer change_to_root_user() */
1084 }
1085
1086 static void smbd_impersonate_conn_vuid_before_timer_handler(
1087                 struct tevent_context *wrap_ev,
1088                 void *private_data,
1089                 struct tevent_context *main_ev,
1090                 struct tevent_timer *te,
1091                 struct timeval requested_time,
1092                 struct timeval trigger_time,
1093                 const char *handler_name,
1094                 const char *location)
1095 {
1096         struct smbd_impersonate_conn_vuid_state *state = talloc_get_type_abort(
1097                 private_data, struct smbd_impersonate_conn_vuid_state);
1098         struct timeval_buf requested_buf;
1099         struct timeval_buf trigger_buf;
1100         bool ok;
1101
1102         DEBUG(11,("%s: te[%p] requested_time[%s] trigger_time[%s] "
1103                   "handler_name[%s] location[%s]\n",
1104                   __func__, te,
1105                   timeval_str_buf(&requested_time, true, true, &requested_buf),
1106                   timeval_str_buf(&trigger_time, true, true, &trigger_buf),
1107                   handler_name, location));
1108
1109         ok = change_to_user(state->conn, state->vuid);
1110         if (!ok) {
1111                 smb_panic("smbd_impersonate_conn_vuid_before_use() - failed");
1112                 return;
1113         }
1114
1115         DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1116                   __func__, state->conn->session_info->unix_info->unix_name,
1117                   (uintmax_t)geteuid(), (uintmax_t)getegid(),
1118                   state->conn->cwd_fname->base_name));
1119 }
1120
1121 static void smbd_impersonate_conn_vuid_after_timer_handler(
1122                 struct tevent_context *wrap_ev,
1123                 void *private_data,
1124                 struct tevent_context *main_ev,
1125                 struct tevent_timer *te,
1126                 struct timeval requested_time,
1127                 struct timeval trigger_time,
1128                 const char *handler_name,
1129                 const char *location)
1130 {
1131         DEBUG(11,("%s: te[%p] handler_name[%s] location[%s]\n",
1132                   __func__, te, handler_name, location));
1133
1134         /* be lazy and defer change_to_root_user() */
1135 }
1136
1137 static void smbd_impersonate_conn_vuid_before_immediate_handler(
1138                 struct tevent_context *wrap_ev,
1139                 void *private_data,
1140                 struct tevent_context *main_ev,
1141                 struct tevent_immediate *im,
1142                 const char *handler_name,
1143                 const char *location)
1144 {
1145         struct smbd_impersonate_conn_vuid_state *state = talloc_get_type_abort(
1146                 private_data, struct smbd_impersonate_conn_vuid_state);
1147         bool ok;
1148
1149         DEBUG(11,("%s: im[%p] handler_name[%s] location[%s]\n",
1150                   __func__, im, handler_name, location));
1151
1152         ok = change_to_user(state->conn, state->vuid);
1153         if (!ok) {
1154                 smb_panic("smbd_impersonate_conn_vuid_before_use() - failed");
1155                 return;
1156         }
1157
1158         DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1159                   __func__, state->conn->session_info->unix_info->unix_name,
1160                   (uintmax_t)geteuid(), (uintmax_t)getegid(),
1161                   state->conn->cwd_fname->base_name));
1162 }
1163
1164 static void smbd_impersonate_conn_vuid_after_immediate_handler(
1165                 struct tevent_context *wrap_ev,
1166                 void *private_data,
1167                 struct tevent_context *main_ev,
1168                 struct tevent_immediate *im,
1169                 const char *handler_name,
1170                 const char *location)
1171 {
1172         DEBUG(11,("%s: im[%p] handler_name[%s] location[%s]\n",
1173                   __func__, im, handler_name, location));
1174
1175         /* be lazy and defer unbecome_user() */
1176 }
1177
1178 static void smbd_impersonate_conn_vuid_before_signal_handler(
1179                 struct tevent_context *wrap_ev,
1180                 void *private_data,
1181                 struct tevent_context *main_ev,
1182                 struct tevent_signal *se,
1183                 int signum,
1184                 int count,
1185                 void *siginfo,
1186                 const char *handler_name,
1187                 const char *location)
1188 {
1189         struct smbd_impersonate_conn_vuid_state *state = talloc_get_type_abort(
1190                 private_data, struct smbd_impersonate_conn_vuid_state);
1191         bool ok;
1192
1193         DEBUG(11,("%s: se[%p] signum[%d] count[%d] siginfo[%p] "
1194                   "handler_name[%s] location[%s]\n",
1195                   __func__, se, signum, count, siginfo, handler_name, location));
1196
1197         ok = change_to_user(state->conn, state->vuid);
1198         if (!ok) {
1199                 smb_panic("smbd_impersonate_conn_vuid_before_use() - failed");
1200                 return;
1201         }
1202
1203         DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1204                   __func__, state->conn->session_info->unix_info->unix_name,
1205                   (uintmax_t)geteuid(), (uintmax_t)getegid(),
1206                   state->conn->cwd_fname->base_name));
1207 }
1208
1209 static void smbd_impersonate_conn_vuid_after_signal_handler(
1210                 struct tevent_context *wrap_ev,
1211                 void *private_data,
1212                 struct tevent_context *main_ev,
1213                 struct tevent_signal *se,
1214                 int signum,
1215                 int count,
1216                 void *siginfo,
1217                 const char *handler_name,
1218                 const char *location)
1219 {
1220         DEBUG(11,("%s: se[%p] handler_name[%s] location[%s]\n",
1221                   __func__, se, handler_name, location));
1222
1223         /* be lazy and defer change_to_root_user() */
1224 }
1225
1226 static const struct tevent_wrapper_ops smbd_impersonate_conn_vuid_ops = {
1227         .name                           = "smbd_impersonate_conn_vuid",
1228         .before_use                     = smbd_impersonate_conn_vuid_before_use,
1229         .after_use                      = smbd_impersonate_conn_vuid_after_use,
1230         .before_fd_handler              = smbd_impersonate_conn_vuid_before_fd_handler,
1231         .after_fd_handler               = smbd_impersonate_conn_vuid_after_fd_handler,
1232         .before_timer_handler           = smbd_impersonate_conn_vuid_before_timer_handler,
1233         .after_timer_handler            = smbd_impersonate_conn_vuid_after_timer_handler,
1234         .before_immediate_handler       = smbd_impersonate_conn_vuid_before_immediate_handler,
1235         .after_immediate_handler        = smbd_impersonate_conn_vuid_after_immediate_handler,
1236         .before_signal_handler          = smbd_impersonate_conn_vuid_before_signal_handler,
1237         .after_signal_handler           = smbd_impersonate_conn_vuid_after_signal_handler,
1238 };
1239
1240 struct tevent_context *smbd_impersonate_conn_vuid_create(
1241                                 struct tevent_context *main_ev,
1242                                 struct connection_struct *conn,
1243                                 uint64_t vuid)
1244 {
1245         struct tevent_context *ev = NULL;
1246         struct smbd_impersonate_conn_vuid_state *state = NULL;
1247
1248         ev = tevent_context_wrapper_create(main_ev,
1249                                            conn,
1250                                            &smbd_impersonate_conn_vuid_ops,
1251                                            &state,
1252                                            struct smbd_impersonate_conn_vuid_state);
1253         if (ev == NULL) {
1254                 return NULL;
1255         }
1256         state->conn = conn;
1257         state->vuid = vuid;
1258
1259         return ev;
1260 }
1261
1262 struct smbd_impersonate_conn_sess_state {
1263         struct connection_struct *conn;
1264         struct auth_session_info *session_info;
1265 };
1266
1267 static bool smbd_impersonate_conn_sess_before_use(struct tevent_context *wrap_ev,
1268                                                   void *private_data,
1269                                                   struct tevent_context *main_ev,
1270                                                   const char *location)
1271 {
1272         struct smbd_impersonate_conn_sess_state *state = talloc_get_type_abort(
1273                 private_data, struct smbd_impersonate_conn_sess_state);
1274         bool ok;
1275
1276         DEBUG(11,("%s: impersonating user[%s] wrap_ev[%p] main_ev[%p] "
1277                   "location[%s] old uid[%ju] old gid[%ju] cwd[%s]\n",
1278                   __func__, state->session_info->unix_info->unix_name,
1279                   wrap_ev, main_ev, location,
1280                   (uintmax_t)geteuid(), (uintmax_t)getegid(),
1281                   state->conn->cwd_fname->base_name));
1282
1283         ok = become_user_by_session(state->conn, state->session_info);
1284         if (!ok) {
1285                 return false;
1286         }
1287
1288         DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1289                   __func__, state->conn->session_info->unix_info->unix_name,
1290                   (uintmax_t)geteuid(), (uintmax_t)getegid(),
1291                   state->conn->cwd_fname->base_name));
1292
1293         return true;
1294 }
1295
1296 static void smbd_impersonate_conn_sess_after_use(struct tevent_context *wrap_ev,
1297                                                  void *private_data,
1298                                                  struct tevent_context *main_ev,
1299                                                  const char *location)
1300 {
1301         struct smbd_impersonate_conn_sess_state *state = talloc_get_type_abort(
1302                 private_data, struct smbd_impersonate_conn_sess_state);
1303         bool ok;
1304
1305         DEBUG(11,("%s: deimpersonating[%s] uid[%ju] gid[%ju] cwd[%s] "
1306                   "location[%s]\n",
1307                   __func__, state->session_info->unix_info->unix_name,
1308                   (uintmax_t)geteuid(), (uintmax_t)getegid(),
1309                   state->conn->cwd_fname->base_name, location));
1310
1311         ok = unbecome_user();
1312         if (!ok) {
1313                 smb_panic("smbd_impersonate_conn_sess_after_use() - failed");
1314                 return;
1315         }
1316
1317         DEBUG(11,("%s: deimpersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1318                   __func__, state->conn->session_info->unix_info->unix_name,
1319                   (uintmax_t)geteuid(), (uintmax_t)getegid(),
1320                   state->conn->cwd_fname->base_name));
1321 }
1322
1323 static void smbd_impersonate_conn_sess_before_fd_handler(
1324                 struct tevent_context *wrap_ev,
1325                 void *private_data,
1326                 struct tevent_context *main_ev,
1327                 struct tevent_fd *fde,
1328                 uint16_t flags,
1329                 const char *handler_name,
1330                 const char *location)
1331 {
1332         struct smbd_impersonate_conn_sess_state *state = talloc_get_type_abort(
1333                 private_data, struct smbd_impersonate_conn_sess_state);
1334         bool ok;
1335
1336         DEBUG(11,("%s: fde[%p] flags[%ju] handler_name[%s] location[%s]\n",
1337                   __func__, fde, (uintmax_t)flags, handler_name, location));
1338
1339         ok = change_to_user_by_session(state->conn, state->session_info);
1340         if (!ok) {
1341                 smb_panic("smbd_impersonate_conn_sess_before_fd_handler failed");
1342                 return;
1343         }
1344
1345         DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1346                   __func__, state->conn->session_info->unix_info->unix_name,
1347                   (uintmax_t)geteuid(), (uintmax_t)getegid(),
1348                   state->conn->cwd_fname->base_name));
1349 }
1350
1351 static void smbd_impersonate_conn_sess_after_fd_handler(struct tevent_context *wrap_ev,
1352                                                         void *private_data,
1353                                                         struct tevent_context *main_ev,
1354                                                         struct tevent_fd *fde,
1355                                                         uint16_t flags,
1356                                                         const char *handler_name,
1357                                                         const char *location)
1358 {
1359         DEBUG(11,("%s: fde[%p] handler_name[%s] location[%s]\n",
1360                   __func__, fde, handler_name, location));
1361
1362         /* be lazy and defer change_to_root_user() */
1363 }
1364
1365 static void smbd_impersonate_conn_sess_before_timer_handler(
1366                 struct tevent_context *wrap_ev,
1367                 void *private_data,
1368                 struct tevent_context *main_ev,
1369                 struct tevent_timer *te,
1370                 struct timeval requested_time,
1371                 struct timeval trigger_time,
1372                 const char *handler_name,
1373                 const char *location)
1374 {
1375         struct smbd_impersonate_conn_sess_state *state = talloc_get_type_abort(
1376                 private_data, struct smbd_impersonate_conn_sess_state);
1377         struct timeval_buf requested_buf;
1378         struct timeval_buf trigger_buf;
1379         bool ok;
1380
1381         DEBUG(11,("%s: te[%p] requested_time[%s] trigger_time[%s] "
1382                   "handler_name[%s] location[%s]\n",
1383                   __func__, te,
1384                   timeval_str_buf(&requested_time, true, true, &requested_buf),
1385                   timeval_str_buf(&trigger_time, true, true, &trigger_buf),
1386                   handler_name, location));
1387
1388         ok = change_to_user_by_session(state->conn, state->session_info);
1389         if (!ok) {
1390                 smb_panic("smbd_impersonate_conn_sess_before_tm_handler failed");
1391                 return;
1392         }
1393
1394         DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1395                   __func__, state->conn->session_info->unix_info->unix_name,
1396                   (uintmax_t)geteuid(), (uintmax_t)getegid(),
1397                   state->conn->cwd_fname->base_name));
1398 }
1399
1400 static void smbd_impersonate_conn_sess_after_timer_handler(
1401                 struct tevent_context *wrap_ev,
1402                 void *private_data,
1403                 struct tevent_context *main_ev,
1404                 struct tevent_timer *te,
1405                 struct timeval requested_time,
1406                 struct timeval trigger_time,
1407                 const char *handler_name,
1408                 const char *location)
1409 {
1410         DEBUG(11,("%s: te[%p] handler_name[%s] location[%s]\n",
1411                   __func__, te, handler_name, location));
1412
1413         /* be lazy and defer change_to_root_user() */
1414 }
1415
1416 static void smbd_impersonate_conn_sess_before_immediate_handler(
1417                 struct tevent_context *wrap_ev,
1418                 void *private_data,
1419                 struct tevent_context *main_ev,
1420                 struct tevent_immediate *im,
1421                 const char *handler_name,
1422                 const char *location)
1423 {
1424         struct smbd_impersonate_conn_sess_state *state = talloc_get_type_abort(
1425                 private_data, struct smbd_impersonate_conn_sess_state);
1426         bool ok;
1427
1428         DEBUG(11,("%s: im[%p] handler_name[%s] location[%s]\n",
1429                   __func__, im, handler_name, location));
1430
1431         ok = change_to_user_by_session(state->conn, state->session_info);
1432         if (!ok) {
1433                 smb_panic("smbd_impersonate_conn_sess_before_im_handler failed");
1434                 return;
1435         }
1436
1437         DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1438                   __func__, state->conn->session_info->unix_info->unix_name,
1439                   (uintmax_t)geteuid(), (uintmax_t)getegid(),
1440                   state->conn->cwd_fname->base_name));
1441 }
1442
1443 static void smbd_impersonate_conn_sess_after_immediate_handler(
1444                 struct tevent_context *wrap_ev,
1445                 void *private_data,
1446                 struct tevent_context *main_ev,
1447                 struct tevent_immediate *im,
1448                 const char *handler_name,
1449                 const char *location)
1450 {
1451         DEBUG(11,("%s: im[%p] handler_name[%s] location[%s]\n",
1452                   __func__, im, handler_name, location));
1453
1454         /* be lazy and defer unbecome_user() */
1455 }
1456
1457 static void smbd_impersonate_conn_sess_before_signal_handler(
1458                 struct tevent_context *wrap_ev,
1459                 void *private_data,
1460                 struct tevent_context *main_ev,
1461                 struct tevent_signal *se,
1462                 int signum,
1463                 int count,
1464                 void *siginfo,
1465                 const char *handler_name,
1466                 const char *location)
1467 {
1468         struct smbd_impersonate_conn_sess_state *state = talloc_get_type_abort(
1469                 private_data, struct smbd_impersonate_conn_sess_state);
1470         bool ok;
1471
1472         DEBUG(11,("%s: se[%p] signum[%d] count[%d] siginfo[%p] "
1473                   "handler_name[%s] location[%s]\n",
1474                   __func__, se, signum, count, siginfo, handler_name, location));
1475
1476         ok = change_to_user_by_session(state->conn, state->session_info);
1477         if (!ok) {
1478                 smb_panic("smbd_impersonate_conn_sess_before_si_handler failed");
1479                 return;
1480         }
1481
1482         DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1483                   __func__, state->conn->session_info->unix_info->unix_name,
1484                   (uintmax_t)geteuid(), (uintmax_t)getegid(),
1485                   state->conn->cwd_fname->base_name));
1486 }
1487
1488 static void smbd_impersonate_conn_sess_after_signal_handler(
1489                 struct tevent_context *wrap_ev,
1490                 void *private_data,
1491                 struct tevent_context *main_ev,
1492                 struct tevent_signal *se,
1493                 int signum,
1494                 int count,
1495                 void *siginfo,
1496                 const char *handler_name,
1497                 const char *location)
1498 {
1499         DEBUG(11,("%s: se[%p] handler_name[%s] location[%s]\n",
1500                   __func__, se, handler_name, location));
1501
1502         /* be lazy and defer change_to_root_user() */
1503 }
1504
1505 static const struct tevent_wrapper_ops smbd_impersonate_conn_sess_ops = {
1506         .name                           = "smbd_impersonate_conn_sess",
1507         .before_use                     = smbd_impersonate_conn_sess_before_use,
1508         .after_use                      = smbd_impersonate_conn_sess_after_use,
1509         .before_fd_handler              = smbd_impersonate_conn_sess_before_fd_handler,
1510         .after_fd_handler               = smbd_impersonate_conn_sess_after_fd_handler,
1511         .before_timer_handler           = smbd_impersonate_conn_sess_before_timer_handler,
1512         .after_timer_handler            = smbd_impersonate_conn_sess_after_timer_handler,
1513         .before_immediate_handler       = smbd_impersonate_conn_sess_before_immediate_handler,
1514         .after_immediate_handler        = smbd_impersonate_conn_sess_after_immediate_handler,
1515         .before_signal_handler          = smbd_impersonate_conn_sess_before_signal_handler,
1516         .after_signal_handler           = smbd_impersonate_conn_sess_after_signal_handler,
1517 };
1518
1519 struct tevent_context *smbd_impersonate_conn_sess_create(
1520                                 struct tevent_context *main_ev,
1521                                 struct connection_struct *conn,
1522                                 struct auth_session_info *session_info)
1523 {
1524         struct tevent_context *ev = NULL;
1525         struct smbd_impersonate_conn_sess_state *state = NULL;
1526
1527         ev = tevent_context_wrapper_create(main_ev,
1528                                            conn,
1529                                            &smbd_impersonate_conn_sess_ops,
1530                                            &state,
1531                                            struct smbd_impersonate_conn_sess_state);
1532         if (ev == NULL) {
1533                 return NULL;
1534         }
1535         state->conn = conn;
1536         state->session_info = session_info;
1537
1538         return ev;
1539 }
1540
1541 struct smbd_impersonate_root_state {
1542         uint8_t _dummy;
1543 };
1544
1545 static bool smbd_impersonate_root_before_use(struct tevent_context *wrap_ev,
1546                                              void *private_data,
1547                                              struct tevent_context *main_ev,
1548                                              const char *location)
1549 {
1550         DEBUG(11,("%s: wrap_ev[%p] main_ev[%p] location[%s]"
1551                   "uid[%ju] gid[%ju]\n",
1552                   __func__, wrap_ev, main_ev, location,
1553                   (uintmax_t)geteuid(), (uintmax_t)getegid()));
1554
1555         become_root();
1556         return true;
1557 }
1558
1559 static void smbd_impersonate_root_after_use(struct tevent_context *wrap_ev,
1560                                             void *private_data,
1561                                             struct tevent_context *main_ev,
1562                                             const char *location)
1563 {
1564         unbecome_root();
1565
1566         DEBUG(11,("%s: uid[%ju] gid[%ju] location[%s]\n",
1567                   __func__, (uintmax_t)geteuid(), (uintmax_t)getegid(),
1568                   location));
1569 }
1570
1571 static void smbd_impersonate_root_before_fd_handler(struct tevent_context *wrap_ev,
1572                                                 void *private_data,
1573                                                 struct tevent_context *main_ev,
1574                                                 struct tevent_fd *fde,
1575                                                 uint16_t flags,
1576                                                 const char *handler_name,
1577                                                 const char *location)
1578 {
1579         DEBUG(11,("%s: fde[%p] flags[%ju] handler_name[%s] location[%s]\n",
1580                   __func__, fde, (uintmax_t)flags, handler_name, location));
1581
1582         smbd_impersonate_root_before_use(wrap_ev, private_data, main_ev, location);
1583 }
1584
1585 static void smbd_impersonate_root_after_fd_handler(struct tevent_context *wrap_ev,
1586                                                 void *private_data,
1587                                                 struct tevent_context *main_ev,
1588                                                 struct tevent_fd *fde,
1589                                                 uint16_t flags,
1590                                                 const char *handler_name,
1591                                                 const char *location)
1592 {
1593         DEBUG(11,("%s: fde[%p] handler_name[%s] location[%s]\n",
1594                   __func__, fde, handler_name, location));
1595
1596         smbd_impersonate_root_after_use(wrap_ev, private_data, main_ev, location);
1597 }
1598
1599 static void smbd_impersonate_root_before_timer_handler(struct tevent_context *wrap_ev,
1600                                                 void *private_data,
1601                                                 struct tevent_context *main_ev,
1602                                                 struct tevent_timer *te,
1603                                                 struct timeval requested_time,
1604                                                 struct timeval trigger_time,
1605                                                 const char *handler_name,
1606                                                 const char *location)
1607 {
1608         struct timeval_buf requested_buf;
1609         struct timeval_buf trigger_buf;
1610
1611         DEBUG(11,("%s: te[%p] requested_time[%s] trigger_time[%s] "
1612                   "handler_name[%s] location[%s]\n",
1613                   __func__, te,
1614                   timeval_str_buf(&requested_time, true, true, &requested_buf),
1615                   timeval_str_buf(&trigger_time, true, true, &trigger_buf),
1616                   handler_name, location));
1617
1618         smbd_impersonate_root_before_use(wrap_ev, private_data, main_ev, location);
1619 }
1620
1621 static void smbd_impersonate_root_after_timer_handler(struct tevent_context *wrap_ev,
1622                                                 void *private_data,
1623                                                 struct tevent_context *main_ev,
1624                                                 struct tevent_timer *te,
1625                                                 struct timeval requested_time,
1626                                                 struct timeval trigger_time,
1627                                                 const char *handler_name,
1628                                                 const char *location)
1629 {
1630         DEBUG(11,("%s: te[%p] handler_name[%s] location[%s]\n",
1631                   __func__, te, handler_name, location));
1632
1633         smbd_impersonate_root_after_use(wrap_ev, private_data, main_ev, location);
1634 }
1635
1636 static void smbd_impersonate_root_before_immediate_handler(struct tevent_context *wrap_ev,
1637                                                 void *private_data,
1638                                                 struct tevent_context *main_ev,
1639                                                 struct tevent_immediate *im,
1640                                                 const char *handler_name,
1641                                                 const char *location)
1642 {
1643         DEBUG(11,("%s: im[%p] handler_name[%s] location[%s]\n",
1644                   __func__, im, handler_name, location));
1645
1646         smbd_impersonate_root_before_use(wrap_ev, private_data, main_ev, location);
1647 }
1648
1649 static void smbd_impersonate_root_after_immediate_handler(struct tevent_context *wrap_ev,
1650                                                 void *private_data,
1651                                                 struct tevent_context *main_ev,
1652                                                 struct tevent_immediate *im,
1653                                                 const char *handler_name,
1654                                                 const char *location)
1655 {
1656         DEBUG(11,("%s: im[%p] handler_name[%s] location[%s]\n",
1657                   __func__, im, handler_name, location));
1658
1659         smbd_impersonate_root_after_use(wrap_ev, private_data, main_ev, location);
1660 }
1661
1662 static void smbd_impersonate_root_before_signal_handler(struct tevent_context *wrap_ev,
1663                                                 void *private_data,
1664                                                 struct tevent_context *main_ev,
1665                                                 struct tevent_signal *se,
1666                                                 int signum,
1667                                                 int count,
1668                                                 void *siginfo,
1669                                                 const char *handler_name,
1670                                                 const char *location)
1671 {
1672         DEBUG(11,("%s: se[%p] signum[%d] count[%d] siginfo[%p] "
1673                   "handler_name[%s] location[%s]\n",
1674                   __func__, se, signum, count, siginfo, handler_name, location));
1675
1676         smbd_impersonate_root_before_use(wrap_ev, private_data, main_ev, location);
1677 }
1678
1679 static void smbd_impersonate_root_after_signal_handler(struct tevent_context *wrap_ev,
1680                                                 void *private_data,
1681                                                 struct tevent_context *main_ev,
1682                                                 struct tevent_signal *se,
1683                                                 int signum,
1684                                                 int count,
1685                                                 void *siginfo,
1686                                                 const char *handler_name,
1687                                                 const char *location)
1688 {
1689         DEBUG(11,("%s: se[%p] handler_name[%s] location[%s]\n",
1690                   __func__, se, handler_name, location));
1691
1692         smbd_impersonate_root_after_use(wrap_ev, private_data, main_ev, location);
1693 }
1694
1695 static const struct tevent_wrapper_ops smbd_impersonate_root_ops = {
1696         .name                           = "smbd_impersonate_root",
1697         .before_use                     = smbd_impersonate_root_before_use,
1698         .after_use                      = smbd_impersonate_root_after_use,
1699         .before_fd_handler              = smbd_impersonate_root_before_fd_handler,
1700         .after_fd_handler               = smbd_impersonate_root_after_fd_handler,
1701         .before_timer_handler           = smbd_impersonate_root_before_timer_handler,
1702         .after_timer_handler            = smbd_impersonate_root_after_timer_handler,
1703         .before_immediate_handler       = smbd_impersonate_root_before_immediate_handler,
1704         .after_immediate_handler        = smbd_impersonate_root_after_immediate_handler,
1705         .before_signal_handler          = smbd_impersonate_root_before_signal_handler,
1706         .after_signal_handler           = smbd_impersonate_root_after_signal_handler,
1707 };
1708
1709 struct tevent_context *smbd_impersonate_root_create(struct tevent_context *main_ev)
1710 {
1711         struct tevent_context *ev = NULL;
1712         struct smbd_impersonate_root_state *state = NULL;
1713
1714         ev = tevent_context_wrapper_create(main_ev,
1715                                            main_ev,
1716                                            &smbd_impersonate_root_ops,
1717                                            &state,
1718                                            struct smbd_impersonate_root_state);
1719         if (ev == NULL) {
1720                 return NULL;
1721         }
1722
1723         return ev;
1724 }
1725
1726 struct smbd_impersonate_guest_state {
1727         uint8_t _dummy;
1728 };
1729
1730 static bool smbd_impersonate_guest_before_use(struct tevent_context *wrap_ev,
1731                                               void *private_data,
1732                                               struct tevent_context *main_ev,
1733                                               const char *location)
1734 {
1735         DEBUG(11,("%s: wrap_ev[%p] main_ev[%p] location[%s]"
1736                   "uid[%ju] gid[%ju]\n",
1737                   __func__, wrap_ev, main_ev, location,
1738                   (uintmax_t)geteuid(), (uintmax_t)getegid()));
1739
1740         return become_guest();
1741 }
1742
1743 static void smbd_impersonate_guest_after_use(struct tevent_context *wrap_ev,
1744                                              void *private_data,
1745                                              struct tevent_context *main_ev,
1746                                              const char *location)
1747 {
1748         unbecome_guest();
1749
1750         DEBUG(11,("%s: uid[%ju] gid[%ju] location[%s]\n",
1751                   __func__, (uintmax_t)geteuid(), (uintmax_t)getegid(),
1752                   location));
1753 }
1754
1755 static void smbd_impersonate_guest_before_fd_handler(struct tevent_context *wrap_ev,
1756                                                 void *private_data,
1757                                                 struct tevent_context *main_ev,
1758                                                 struct tevent_fd *fde,
1759                                                 uint16_t flags,
1760                                                 const char *handler_name,
1761                                                 const char *location)
1762 {
1763         bool ok;
1764
1765         DEBUG(11,("%s: fde[%p] flags[%ju] handler_name[%s] location[%s]\n",
1766                   __func__, fde, (uintmax_t)flags, handler_name, location));
1767
1768         ok = smbd_impersonate_guest_before_use(wrap_ev, private_data,
1769                                                 main_ev, location);
1770         if (!ok) {
1771                 smb_panic("smbd_impersonate_guest_before_use() - failed");
1772                 return;
1773         }
1774 }
1775
1776 static void smbd_impersonate_guest_after_fd_handler(struct tevent_context *wrap_ev,
1777                                                 void *private_data,
1778                                                 struct tevent_context *main_ev,
1779                                                 struct tevent_fd *fde,
1780                                                 uint16_t flags,
1781                                                 const char *handler_name,
1782                                                 const char *location)
1783 {
1784         DEBUG(11,("%s: fde[%p] handler_name[%s] location[%s]\n",
1785                   __func__, fde, handler_name, location));
1786
1787         smbd_impersonate_guest_after_use(wrap_ev, private_data, main_ev, location);
1788 }
1789
1790 static void smbd_impersonate_guest_before_timer_handler(struct tevent_context *wrap_ev,
1791                                                 void *private_data,
1792                                                 struct tevent_context *main_ev,
1793                                                 struct tevent_timer *te,
1794                                                 struct timeval requested_time,
1795                                                 struct timeval trigger_time,
1796                                                 const char *handler_name,
1797                                                 const char *location)
1798 {
1799         bool ok;
1800         struct timeval_buf requested_buf;
1801         struct timeval_buf trigger_buf;
1802
1803         DEBUG(11,("%s: te[%p] requested_time[%s] trigger_time[%s] "
1804                   "handler_name[%s] location[%s]\n",
1805                   __func__, te,
1806                   timeval_str_buf(&requested_time, true, true, &requested_buf),
1807                   timeval_str_buf(&trigger_time, true, true, &trigger_buf),
1808                   handler_name, location));
1809
1810         ok = smbd_impersonate_guest_before_use(wrap_ev, private_data,
1811                                                main_ev, location);
1812         if (!ok) {
1813                 smb_panic("smbd_impersonate_guest_before_use() - failed");
1814                 return;
1815         }
1816 }
1817
1818 static void smbd_impersonate_guest_after_timer_handler(struct tevent_context *wrap_ev,
1819                                                 void *private_data,
1820                                                 struct tevent_context *main_ev,
1821                                                 struct tevent_timer *te,
1822                                                 struct timeval requested_time,
1823                                                 struct timeval trigger_time,
1824                                                 const char *handler_name,
1825                                                 const char *location)
1826 {
1827         DEBUG(11,("%s: te[%p] handler_name[%s] location[%s]\n",
1828                   __func__, te, handler_name, location));
1829
1830         smbd_impersonate_guest_after_use(wrap_ev, private_data, main_ev, location);
1831 }
1832
1833 static void smbd_impersonate_guest_before_immediate_handler(struct tevent_context *wrap_ev,
1834                                                 void *private_data,
1835                                                 struct tevent_context *main_ev,
1836                                                 struct tevent_immediate *im,
1837                                                 const char *handler_name,
1838                                                 const char *location)
1839 {
1840         bool ok;
1841
1842         DEBUG(11,("%s: im[%p] handler_name[%s] location[%s]\n",
1843                   __func__, im, handler_name, location));
1844
1845         ok = smbd_impersonate_guest_before_use(wrap_ev, private_data,
1846                                                main_ev, location);
1847         if (!ok) {
1848                 smb_panic("smbd_impersonate_guest_before_use() - failed");
1849                 return;
1850         }
1851 }
1852
1853 static void smbd_impersonate_guest_after_immediate_handler(struct tevent_context *wrap_ev,
1854                                                 void *private_data,
1855                                                 struct tevent_context *main_ev,
1856                                                 struct tevent_immediate *im,
1857                                                 const char *handler_name,
1858                                                 const char *location)
1859 {
1860         DEBUG(11,("%s: im[%p] handler_name[%s] location[%s]\n",
1861                   __func__, im, handler_name, location));
1862
1863         smbd_impersonate_guest_after_use(wrap_ev, private_data, main_ev, location);
1864 }
1865
1866 static void smbd_impersonate_guest_before_signal_handler(struct tevent_context *wrap_ev,
1867                                                 void *private_data,
1868                                                 struct tevent_context *main_ev,
1869                                                 struct tevent_signal *se,
1870                                                 int signum,
1871                                                 int count,
1872                                                 void *siginfo,
1873                                                 const char *handler_name,
1874                                                 const char *location)
1875 {
1876         bool ok;
1877
1878         DEBUG(11,("%s: se[%p] signum[%d] count[%d] siginfo[%p] "
1879                   "handler_name[%s] location[%s]\n",
1880                   __func__, se, signum, count, siginfo, handler_name, location));
1881
1882         ok = smbd_impersonate_guest_before_use(wrap_ev, private_data,
1883                                                main_ev, location);
1884         if (!ok) {
1885                 smb_panic("smbd_impersonate_guest_before_use() - failed");
1886                 return;
1887         }
1888 }
1889
1890 static void smbd_impersonate_guest_after_signal_handler(struct tevent_context *wrap_ev,
1891                                                 void *private_data,
1892                                                 struct tevent_context *main_ev,
1893                                                 struct tevent_signal *se,
1894                                                 int signum,
1895                                                 int count,
1896                                                 void *siginfo,
1897                                                 const char *handler_name,
1898                                                 const char *location)
1899 {
1900         DEBUG(11,("%s: se[%p] handler_name[%s] location[%s]\n",
1901                   __func__, se, handler_name, location));
1902
1903         smbd_impersonate_guest_after_use(wrap_ev, private_data, main_ev, location);
1904 }
1905
1906 static const struct tevent_wrapper_ops smbd_impersonate_guest_ops = {
1907         .name                           = "smbd_impersonate_guest",
1908         .before_use                     = smbd_impersonate_guest_before_use,
1909         .after_use                      = smbd_impersonate_guest_after_use,
1910         .before_fd_handler              = smbd_impersonate_guest_before_fd_handler,
1911         .after_fd_handler               = smbd_impersonate_guest_after_fd_handler,
1912         .before_timer_handler           = smbd_impersonate_guest_before_timer_handler,
1913         .after_timer_handler            = smbd_impersonate_guest_after_timer_handler,
1914         .before_immediate_handler       = smbd_impersonate_guest_before_immediate_handler,
1915         .after_immediate_handler        = smbd_impersonate_guest_after_immediate_handler,
1916         .before_signal_handler          = smbd_impersonate_guest_before_signal_handler,
1917         .after_signal_handler           = smbd_impersonate_guest_after_signal_handler,
1918 };
1919
1920 struct tevent_context *smbd_impersonate_guest_create(struct tevent_context *main_ev)
1921 {
1922         struct tevent_context *ev = NULL;
1923         struct smbd_impersonate_guest_state *state = NULL;
1924
1925         ev = tevent_context_wrapper_create(main_ev,
1926                                            main_ev,
1927                                            &smbd_impersonate_guest_ops,
1928                                            &state,
1929                                            struct smbd_impersonate_guest_state);
1930         if (ev == NULL) {
1931                 return NULL;
1932         }
1933
1934         return ev;
1935 }