fcc4d51a698c544365b5f2b9f01098372ee72345
[bbaumbach/samba-autobuild/.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 "lib/util/time_basic.h"
29
30 struct smbd_impersonate_debug_state {
31         int dbg_lvl;
32         const char *name;
33 };
34
35 static bool smbd_impersonate_debug_before_use(struct tevent_context *wrap_ev,
36                                               void *private_data,
37                                               struct tevent_context *main_ev,
38                                               const char *location)
39 {
40         struct smbd_impersonate_debug_state *state =
41                 (struct smbd_impersonate_debug_state *)private_data;
42
43         DEBUG(state->dbg_lvl, (
44               "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] location[%s]\n",
45               __func__, state->name, wrap_ev, state, main_ev, location));
46
47         return true;
48 }
49
50 static void smbd_impersonate_debug_after_use(struct tevent_context *wrap_ev,
51                                              void *private_data,
52                                              struct tevent_context *main_ev,
53                                              const char *location)
54 {
55         struct smbd_impersonate_debug_state *state =
56                 (struct smbd_impersonate_debug_state *)private_data;
57
58         DEBUG(state->dbg_lvl, (
59               "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] location[%s]\n",
60               __func__, state->name, wrap_ev, state, main_ev, location));
61 }
62
63 static void smbd_impersonate_debug_before_fd_handler(struct tevent_context *wrap_ev,
64                                                 void *private_data,
65                                                 struct tevent_context *main_ev,
66                                                 struct tevent_fd *fde,
67                                                 uint16_t flags,
68                                                 const char *handler_name,
69                                                 const char *location)
70 {
71         struct smbd_impersonate_debug_state *state =
72                 (struct smbd_impersonate_debug_state *)private_data;
73
74         DEBUG(state->dbg_lvl, (
75               "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] "
76               "fde[%p] flags[0x%X] handler_name[%s] location[%s]\n",
77               __func__, state->name, wrap_ev, state, main_ev,
78               fde, flags, handler_name, location));
79 }
80
81 static void smbd_impersonate_debug_after_fd_handler(struct tevent_context *wrap_ev,
82                                                 void *private_data,
83                                                 struct tevent_context *main_ev,
84                                                 struct tevent_fd *fde,
85                                                 uint16_t flags,
86                                                 const char *handler_name,
87                                                 const char *location)
88 {
89         struct smbd_impersonate_debug_state *state =
90                 (struct smbd_impersonate_debug_state *)private_data;
91
92         DEBUG(state->dbg_lvl, (
93               "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] "
94               "fde[%p] flags[0x%X] handler_name[%s] location[%s]\n",
95               __func__, state->name, wrap_ev, state, main_ev,
96               fde, flags, handler_name, location));
97 }
98
99 static void smbd_impersonate_debug_before_timer_handler(struct tevent_context *wrap_ev,
100                                                 void *private_data,
101                                                 struct tevent_context *main_ev,
102                                                 struct tevent_timer *te,
103                                                 struct timeval requested_time,
104                                                 struct timeval trigger_time,
105                                                 const char *handler_name,
106                                                 const char *location)
107 {
108         struct smbd_impersonate_debug_state *state =
109                 (struct smbd_impersonate_debug_state *)private_data;
110         struct timeval_buf requested_buf;
111         struct timeval_buf trigger_buf;
112
113         DEBUG(state->dbg_lvl, (
114               "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] "
115               "te[%p] requested_time[%s] trigger_time[%s] handler_name[%s] location[%s]\n",
116               __func__, state->name, wrap_ev, state, main_ev, te,
117               timeval_str_buf(&requested_time, true, true, &requested_buf),
118               timeval_str_buf(&trigger_time, true, true, &trigger_buf),
119               handler_name, location));
120 }
121
122 static void smbd_impersonate_debug_after_timer_handler(struct tevent_context *wrap_ev,
123                                                 void *private_data,
124                                                 struct tevent_context *main_ev,
125                                                 struct tevent_timer *te,
126                                                 struct timeval requested_time,
127                                                 struct timeval trigger_time,
128                                                 const char *handler_name,
129                                                 const char *location)
130 {
131         struct smbd_impersonate_debug_state *state =
132                 (struct smbd_impersonate_debug_state *)private_data;
133         struct timeval_buf requested_buf;
134         struct timeval_buf trigger_buf;
135
136         DEBUG(state->dbg_lvl, (
137               "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] "
138               "te[%p] requested_time[%s] trigger_time[%s] handler_name[%s] location[%s]\n",
139               __func__, state->name, wrap_ev, state, main_ev, te,
140               timeval_str_buf(&requested_time, true, true, &requested_buf),
141               timeval_str_buf(&trigger_time, true, true, &trigger_buf),
142               handler_name, location));
143 }
144
145 static void smbd_impersonate_debug_before_immediate_handler(struct tevent_context *wrap_ev,
146                                                 void *private_data,
147                                                 struct tevent_context *main_ev,
148                                                 struct tevent_immediate *im,
149                                                 const char *handler_name,
150                                                 const char *location)
151 {
152         struct smbd_impersonate_debug_state *state =
153                 (struct smbd_impersonate_debug_state *)private_data;
154
155         DEBUG(state->dbg_lvl, (
156               "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] "
157               "im[%p] handler_name[%s] location[%s]\n",
158               __func__, state->name, wrap_ev, state, main_ev,
159               im, handler_name, location));
160 }
161
162 static void smbd_impersonate_debug_after_immediate_handler(struct tevent_context *wrap_ev,
163                                                 void *private_data,
164                                                 struct tevent_context *main_ev,
165                                                 struct tevent_immediate *im,
166                                                 const char *handler_name,
167                                                 const char *location)
168 {
169         struct smbd_impersonate_debug_state *state =
170                 (struct smbd_impersonate_debug_state *)private_data;
171
172         DEBUG(state->dbg_lvl, (
173               "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] "
174               "im[%p] handler_name[%s] location[%s]\n",
175               __func__, state->name, wrap_ev, state, main_ev,
176               im, handler_name, location));
177 }
178
179 static void smbd_impersonate_debug_before_signal_handler(struct tevent_context *wrap_ev,
180                                                 void *private_data,
181                                                 struct tevent_context *main_ev,
182                                                 struct tevent_signal *se,
183                                                 int signum,
184                                                 int count,
185                                                 void *siginfo,
186                                                 const char *handler_name,
187                                                 const char *location)
188 {
189         struct smbd_impersonate_debug_state *state =
190                 (struct smbd_impersonate_debug_state *)private_data;
191
192         DEBUG(state->dbg_lvl, (
193               "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] "
194               "se[%p] signum[%d] count[%d] siginfo[%p] handler_name[%s] location[%s]\n",
195               __func__, state->name, wrap_ev, state, main_ev,
196               se, signum, count, siginfo, handler_name, location));
197 }
198
199 static void smbd_impersonate_debug_after_signal_handler(struct tevent_context *wrap_ev,
200                                                 void *private_data,
201                                                 struct tevent_context *main_ev,
202                                                 struct tevent_signal *se,
203                                                 int signum,
204                                                 int count,
205                                                 void *siginfo,
206                                                 const char *handler_name,
207                                                 const char *location)
208 {
209         struct smbd_impersonate_debug_state *state =
210                 (struct smbd_impersonate_debug_state *)private_data;
211
212         DEBUG(state->dbg_lvl, (
213               "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] "
214               "se[%p] signum[%d] count[%d] siginfo[%p] handler_name[%s] location[%s]\n",
215               __func__, state->name, wrap_ev, state, main_ev,
216               se, signum, count, siginfo, handler_name, location));
217 }
218
219 static const struct tevent_wrapper_ops smbd_impersonate_debug_ops = {
220         .name                           = "smbd_impersonate_debug",
221         .before_use                     = smbd_impersonate_debug_before_use,
222         .after_use                      = smbd_impersonate_debug_after_use,
223         .before_fd_handler              = smbd_impersonate_debug_before_fd_handler,
224         .after_fd_handler               = smbd_impersonate_debug_after_fd_handler,
225         .before_timer_handler           = smbd_impersonate_debug_before_timer_handler,
226         .after_timer_handler            = smbd_impersonate_debug_after_timer_handler,
227         .before_immediate_handler       = smbd_impersonate_debug_before_immediate_handler,
228         .after_immediate_handler        = smbd_impersonate_debug_after_immediate_handler,
229         .before_signal_handler          = smbd_impersonate_debug_before_signal_handler,
230         .after_signal_handler           = smbd_impersonate_debug_after_signal_handler,
231 };
232
233 struct tevent_context *_smbd_impersonate_debug_create(struct tevent_context *main_ev,
234                                                       const char *name,
235                                                       int dbg_lvl,
236                                                       const char *location)
237 {
238         struct tevent_context *wrap_ev = NULL;
239         struct smbd_impersonate_debug_state *state = NULL;
240
241         wrap_ev = tevent_context_wrapper_create(main_ev,
242                                         main_ev,
243                                         &smbd_impersonate_debug_ops,
244                                         &state,
245                                         struct smbd_impersonate_debug_state);
246         if (wrap_ev == NULL) {
247                 return NULL;
248         }
249         state->name = name;
250         state->dbg_lvl = dbg_lvl;
251         DEBUG(state->dbg_lvl, (
252               "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] location[%s]\n",
253               __func__, state->name, wrap_ev, state, main_ev, location));
254
255         return wrap_ev;
256 }
257
258 /* what user is current? */
259 extern struct current_user current_user;
260
261 /****************************************************************************
262  Become the guest user without changing the security context stack.
263 ****************************************************************************/
264
265 bool change_to_guest(void)
266 {
267         struct passwd *pass;
268
269         pass = Get_Pwnam_alloc(talloc_tos(), lp_guest_account());
270         if (!pass) {
271                 return false;
272         }
273
274 #ifdef AIX
275         /* MWW: From AIX FAQ patch to WU-ftpd: call initgroups before 
276            setting IDs */
277         initgroups(pass->pw_name, pass->pw_gid);
278 #endif
279
280         set_sec_ctx(pass->pw_uid, pass->pw_gid, 0, NULL, NULL);
281
282         current_user.conn = NULL;
283         current_user.vuid = UID_FIELD_INVALID;
284         current_user.need_chdir = false;
285         current_user.done_chdir = false;
286
287         TALLOC_FREE(pass);
288
289         return true;
290 }
291
292 /****************************************************************************
293  talloc free the conn->session_info if not used in the vuid cache.
294 ****************************************************************************/
295
296 static void free_conn_session_info_if_unused(connection_struct *conn)
297 {
298         unsigned int i;
299
300         for (i = 0; i < VUID_CACHE_SIZE; i++) {
301                 struct vuid_cache_entry *ent;
302                 ent = &conn->vuid_cache->array[i];
303                 if (ent->vuid != UID_FIELD_INVALID &&
304                                 conn->session_info == ent->session_info) {
305                         return;
306                 }
307         }
308         /* Not used, safe to free. */
309         TALLOC_FREE(conn->user_ev_ctx);
310         TALLOC_FREE(conn->session_info);
311 }
312
313 /****************************************************************************
314   Setup the share access mask for a connection.
315 ****************************************************************************/
316
317 static uint32_t create_share_access_mask(int snum,
318                                 bool readonly_share,
319                                 const struct security_token *token)
320 {
321         uint32_t share_access = 0;
322
323         share_access_check(token,
324                         lp_const_servicename(snum),
325                         MAXIMUM_ALLOWED_ACCESS,
326                         &share_access);
327
328         if (readonly_share) {
329                 share_access &=
330                         ~(SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA |
331                           SEC_FILE_WRITE_EA | SEC_FILE_WRITE_ATTRIBUTE |
332                           SEC_DIR_DELETE_CHILD );
333         }
334
335         if (security_token_has_privilege(token, SEC_PRIV_SECURITY)) {
336                 share_access |= SEC_FLAG_SYSTEM_SECURITY;
337         }
338         if (security_token_has_privilege(token, SEC_PRIV_RESTORE)) {
339                 share_access |= SEC_RIGHTS_PRIV_RESTORE;
340         }
341         if (security_token_has_privilege(token, SEC_PRIV_BACKUP)) {
342                 share_access |= SEC_RIGHTS_PRIV_BACKUP;
343         }
344         if (security_token_has_privilege(token, SEC_PRIV_TAKE_OWNERSHIP)) {
345                 share_access |= SEC_STD_WRITE_OWNER;
346         }
347
348         return share_access;
349 }
350
351 /*******************************************************************
352  Calculate access mask and if this user can access this share.
353 ********************************************************************/
354
355 NTSTATUS check_user_share_access(connection_struct *conn,
356                                 const struct auth_session_info *session_info,
357                                 uint32_t *p_share_access,
358                                 bool *p_readonly_share)
359 {
360         int snum = SNUM(conn);
361         uint32_t share_access = 0;
362         bool readonly_share = false;
363
364         if (!user_ok_token(session_info->unix_info->unix_name,
365                            session_info->info->domain_name,
366                            session_info->security_token, snum)) {
367                 return NT_STATUS_ACCESS_DENIED;
368         }
369
370         readonly_share = is_share_read_only_for_token(
371                 session_info->unix_info->unix_name,
372                 session_info->info->domain_name,
373                 session_info->security_token,
374                 conn);
375
376         share_access = create_share_access_mask(snum,
377                                         readonly_share,
378                                         session_info->security_token);
379
380         if ((share_access & (FILE_READ_DATA|FILE_WRITE_DATA)) == 0) {
381                 /* No access, read or write. */
382                 DBG_NOTICE("user %s connection to %s denied due to share "
383                          "security descriptor.\n",
384                          session_info->unix_info->unix_name,
385                          lp_const_servicename(snum));
386                 return NT_STATUS_ACCESS_DENIED;
387         }
388
389         if (!readonly_share &&
390             !(share_access & FILE_WRITE_DATA)) {
391                 /* smb.conf allows r/w, but the security descriptor denies
392                  * write. Fall back to looking at readonly. */
393                 readonly_share = true;
394                 DBG_INFO("falling back to read-only access-evaluation due to "
395                          "security descriptor\n");
396         }
397
398         *p_share_access = share_access;
399         *p_readonly_share = readonly_share;
400
401         return NT_STATUS_OK;
402 }
403
404 /*******************************************************************
405  Check if a username is OK.
406
407  This sets up conn->session_info with a copy related to this vuser that
408  later code can then mess with.
409 ********************************************************************/
410
411 static bool check_user_ok(connection_struct *conn,
412                         uint64_t vuid,
413                         const struct auth_session_info *session_info,
414                         int snum)
415 {
416         unsigned int i;
417         bool readonly_share = false;
418         bool admin_user = false;
419         struct vuid_cache_entry *ent = NULL;
420         uint32_t share_access = 0;
421         NTSTATUS status;
422
423         for (i=0; i<VUID_CACHE_SIZE; i++) {
424                 ent = &conn->vuid_cache->array[i];
425                 if (ent->vuid == vuid) {
426                         if (vuid == UID_FIELD_INVALID) {
427                                 /*
428                                  * Slow path, we don't care
429                                  * about the array traversal.
430                                 */
431                                 continue;
432                         }
433                         free_conn_session_info_if_unused(conn);
434                         conn->session_info = ent->session_info;
435                         conn->user_ev_ctx = ent->user_ev_ctx;
436                         conn->read_only = ent->read_only;
437                         conn->share_access = ent->share_access;
438                         conn->vuid = ent->vuid;
439                         return(True);
440                 }
441         }
442
443         status = check_user_share_access(conn,
444                                         session_info,
445                                         &share_access,
446                                         &readonly_share);
447         if (!NT_STATUS_IS_OK(status)) {
448                 return false;
449         }
450
451         admin_user = token_contains_name_in_list(
452                 session_info->unix_info->unix_name,
453                 session_info->info->domain_name,
454                 NULL, session_info->security_token, lp_admin_users(snum));
455
456         ent = &conn->vuid_cache->array[conn->vuid_cache->next_entry];
457
458         conn->vuid_cache->next_entry =
459                 (conn->vuid_cache->next_entry + 1) % VUID_CACHE_SIZE;
460
461         TALLOC_FREE(ent->session_info);
462
463         /*
464          * If force_user was set, all session_info's are based on the same
465          * username-based faked one.
466          */
467
468         ent->session_info = copy_session_info(
469                 conn, conn->force_user ? conn->session_info : session_info);
470
471         if (ent->session_info == NULL) {
472                 ent->vuid = UID_FIELD_INVALID;
473                 return false;
474         }
475
476         if (admin_user) {
477                 DEBUG(2,("check_user_ok: user %s is an admin user. "
478                         "Setting uid as %d\n",
479                         ent->session_info->unix_info->unix_name,
480                         sec_initial_uid() ));
481                 ent->session_info->unix_token->uid = sec_initial_uid();
482         }
483
484         if (vuid == UID_FIELD_INVALID) {
485                 ent->user_ev_ctx = smbd_impersonate_conn_sess_create(
486                         conn->sconn->raw_ev_ctx, conn, ent->session_info);
487                 if (ent->user_ev_ctx == NULL) {
488                         TALLOC_FREE(ent->session_info);
489                         ent->vuid = UID_FIELD_INVALID;
490                         return false;
491                 }
492         } else {
493                 ent->user_ev_ctx = smbd_impersonate_conn_vuid_create(
494                         conn->sconn->raw_ev_ctx, conn, vuid);
495                 if (ent->user_ev_ctx == NULL) {
496                         TALLOC_FREE(ent->session_info);
497                         ent->vuid = UID_FIELD_INVALID;
498                         return false;
499                 }
500         }
501
502         /*
503          * It's actually OK to call check_user_ok() with
504          * vuid == UID_FIELD_INVALID as called from change_to_user_by_session().
505          * All this will do is throw away one entry in the cache.
506          */
507
508         ent->vuid = vuid;
509         ent->read_only = readonly_share;
510         ent->share_access = share_access;
511         free_conn_session_info_if_unused(conn);
512         conn->session_info = ent->session_info;
513         conn->vuid = ent->vuid;
514         conn->user_ev_ctx = ent->user_ev_ctx;
515         if (vuid == UID_FIELD_INVALID) {
516                 /*
517                  * Not strictly needed, just make it really
518                  * clear this entry is actually an unused one.
519                  */
520                 ent->read_only = false;
521                 ent->share_access = 0;
522                 ent->session_info = NULL;
523                 ent->user_ev_ctx = NULL;
524         }
525
526         conn->read_only = readonly_share;
527         conn->share_access = share_access;
528
529         return(True);
530 }
531
532 /****************************************************************************
533  Become the user of a connection number without changing the security context
534  stack, but modify the current_user entries.
535 ****************************************************************************/
536
537 static bool change_to_user_internal(connection_struct *conn,
538                                     const struct auth_session_info *session_info,
539                                     uint64_t vuid)
540 {
541         int snum;
542         gid_t gid;
543         uid_t uid;
544         char group_c;
545         int num_groups = 0;
546         gid_t *group_list = NULL;
547         bool ok;
548
549         if ((current_user.conn == conn) &&
550             (current_user.vuid == vuid) &&
551             (current_user.need_chdir == conn->tcon_done) &&
552             (current_user.ut.uid == session_info->unix_token->uid))
553         {
554                 DBG_INFO("Skipping user change - already user\n");
555                 return true;
556         }
557
558         set_current_user_info(session_info->unix_info->sanitized_username,
559                               session_info->unix_info->unix_name,
560                               session_info->info->domain_name);
561
562         snum = SNUM(conn);
563
564         ok = check_user_ok(conn, vuid, session_info, snum);
565         if (!ok) {
566                 DBG_WARNING("SMB user %s (unix user %s) "
567                          "not permitted access to share %s.\n",
568                          session_info->unix_info->sanitized_username,
569                          session_info->unix_info->unix_name,
570                          lp_const_servicename(snum));
571                 return false;
572         }
573
574         uid = conn->session_info->unix_token->uid;
575         gid = conn->session_info->unix_token->gid;
576         num_groups = conn->session_info->unix_token->ngroups;
577         group_list  = conn->session_info->unix_token->groups;
578
579         /*
580          * See if we should force group for this service. If so this overrides
581          * any group set in the force user code.
582          */
583         if((group_c = *lp_force_group(talloc_tos(), snum))) {
584
585                 SMB_ASSERT(conn->force_group_gid != (gid_t)-1);
586
587                 if (group_c == '+') {
588                         int i;
589
590                         /*
591                          * Only force group if the user is a member of the
592                          * service group. Check the group memberships for this
593                          * user (we already have this) to see if we should force
594                          * the group.
595                          */
596                         for (i = 0; i < num_groups; i++) {
597                                 if (group_list[i] == conn->force_group_gid) {
598                                         conn->session_info->unix_token->gid =
599                                                 conn->force_group_gid;
600                                         gid = conn->force_group_gid;
601                                         gid_to_sid(&conn->session_info->security_token
602                                                    ->sids[1], gid);
603                                         break;
604                                 }
605                         }
606                 } else {
607                         conn->session_info->unix_token->gid = conn->force_group_gid;
608                         gid = conn->force_group_gid;
609                         gid_to_sid(&conn->session_info->security_token->sids[1],
610                                    gid);
611                 }
612         }
613
614         /*Set current_user since we will immediately also call set_sec_ctx() */
615         current_user.ut.ngroups = num_groups;
616         current_user.ut.groups  = group_list;
617
618         set_sec_ctx(uid,
619                     gid,
620                     current_user.ut.ngroups,
621                     current_user.ut.groups,
622                     conn->session_info->security_token);
623
624         current_user.conn = conn;
625         current_user.vuid = vuid;
626         current_user.need_chdir = conn->tcon_done;
627
628         if (current_user.need_chdir) {
629                 ok = chdir_current_service(conn);
630                 if (!ok) {
631                         DBG_ERR("chdir_current_service() failed!\n");
632                         return false;
633                 }
634                 current_user.done_chdir = true;
635         }
636
637         if (CHECK_DEBUGLVL(DBGLVL_INFO)) {
638                 struct smb_filename *cwdfname = vfs_GetWd(talloc_tos(), conn);
639                 if (cwdfname == NULL) {
640                         return false;
641                 }
642                 DBG_INFO("Impersonated user: uid=(%d,%d), gid=(%d,%d), cwd=[%s]\n",
643                          (int)getuid(),
644                          (int)geteuid(),
645                          (int)getgid(),
646                          (int)getegid(),
647                          cwdfname->base_name);
648                 TALLOC_FREE(cwdfname);
649         }
650
651         return true;
652 }
653
654 bool change_to_user(connection_struct *conn, uint64_t vuid)
655 {
656         struct user_struct *vuser;
657         int snum = SNUM(conn);
658
659         if (!conn) {
660                 DEBUG(2,("Connection not open\n"));
661                 return(False);
662         }
663
664         vuser = get_valid_user_struct(conn->sconn, vuid);
665         if (vuser == NULL) {
666                 /* Invalid vuid sent */
667                 DBG_WARNING("Invalid vuid %llu used on share %s.\n",
668                             (unsigned long long)vuid,
669                             lp_const_servicename(snum));
670                 return false;
671         }
672
673         return change_to_user_internal(conn, vuser->session_info, vuid);
674 }
675
676 bool change_to_user_by_fsp(struct files_struct *fsp)
677 {
678         return change_to_user(fsp->conn, fsp->vuid);
679 }
680
681 static bool change_to_user_by_session(connection_struct *conn,
682                                       const struct auth_session_info *session_info)
683 {
684         SMB_ASSERT(conn != NULL);
685         SMB_ASSERT(session_info != NULL);
686
687         return change_to_user_internal(conn, session_info, UID_FIELD_INVALID);
688 }
689
690 /****************************************************************************
691  Go back to being root without changing the security context stack,
692  but modify the current_user entries.
693 ****************************************************************************/
694
695 bool smbd_change_to_root_user(void)
696 {
697         set_root_sec_ctx();
698
699         DEBUG(5,("change_to_root_user: now uid=(%d,%d) gid=(%d,%d)\n",
700                 (int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid()));
701
702         current_user.conn = NULL;
703         current_user.vuid = UID_FIELD_INVALID;
704         current_user.need_chdir = false;
705         current_user.done_chdir = false;
706
707         return(True);
708 }
709
710 /****************************************************************************
711  Become the user of an authenticated connected named pipe.
712  When this is called we are currently running as the connection
713  user. Doesn't modify current_user.
714 ****************************************************************************/
715
716 bool smbd_become_authenticated_pipe_user(struct auth_session_info *session_info)
717 {
718         if (!push_sec_ctx())
719                 return False;
720
721         set_sec_ctx(session_info->unix_token->uid, session_info->unix_token->gid,
722                     session_info->unix_token->ngroups, session_info->unix_token->groups,
723                     session_info->security_token);
724
725         DEBUG(5, ("Impersonated user: uid=(%d,%d), gid=(%d,%d)\n",
726                  (int)getuid(),
727                  (int)geteuid(),
728                  (int)getgid(),
729                  (int)getegid()));
730
731         return True;
732 }
733
734 /****************************************************************************
735  Unbecome the user of an authenticated connected named pipe.
736  When this is called we are running as the authenticated pipe
737  user and need to go back to being the connection user. Doesn't modify
738  current_user.
739 ****************************************************************************/
740
741 bool smbd_unbecome_authenticated_pipe_user(void)
742 {
743         return pop_sec_ctx();
744 }
745
746 /****************************************************************************
747  Utility functions used by become_xxx/unbecome_xxx.
748 ****************************************************************************/
749
750 static void push_conn_ctx(void)
751 {
752         struct conn_ctx *ctx_p;
753         extern userdom_struct current_user_info;
754
755         /* Check we don't overflow our stack */
756
757         if (conn_ctx_stack_ndx == MAX_SEC_CTX_DEPTH) {
758                 DEBUG(0, ("Connection context stack overflow!\n"));
759                 smb_panic("Connection context stack overflow!\n");
760         }
761
762         /* Store previous user context */
763         ctx_p = &conn_ctx_stack[conn_ctx_stack_ndx];
764
765         ctx_p->conn = current_user.conn;
766         ctx_p->vuid = current_user.vuid;
767         ctx_p->need_chdir = current_user.need_chdir;
768         ctx_p->done_chdir = current_user.done_chdir;
769         ctx_p->user_info = current_user_info;
770
771         DEBUG(4, ("push_conn_ctx(%llu) : conn_ctx_stack_ndx = %d\n",
772                 (unsigned long long)ctx_p->vuid, conn_ctx_stack_ndx));
773
774         conn_ctx_stack_ndx++;
775 }
776
777 static void pop_conn_ctx(void)
778 {
779         struct conn_ctx *ctx_p;
780
781         /* Check for stack underflow. */
782
783         if (conn_ctx_stack_ndx == 0) {
784                 DEBUG(0, ("Connection context stack underflow!\n"));
785                 smb_panic("Connection context stack underflow!\n");
786         }
787
788         conn_ctx_stack_ndx--;
789         ctx_p = &conn_ctx_stack[conn_ctx_stack_ndx];
790
791         set_current_user_info(ctx_p->user_info.smb_name,
792                               ctx_p->user_info.unix_name,
793                               ctx_p->user_info.domain);
794
795         /*
796          * Check if the current context did a chdir_current_service()
797          * and restore the cwd_fname of the previous context
798          * if needed.
799          */
800         if (current_user.done_chdir && ctx_p->need_chdir) {
801                 int ret;
802
803                 ret = vfs_ChDir(ctx_p->conn, ctx_p->conn->cwd_fname);
804                 if (ret != 0) {
805                         DBG_ERR("vfs_ChDir() failed!\n");
806                         smb_panic("vfs_ChDir() failed!\n");
807                 }
808         }
809
810         current_user.conn = ctx_p->conn;
811         current_user.vuid = ctx_p->vuid;
812         current_user.need_chdir = ctx_p->need_chdir;
813         current_user.done_chdir = ctx_p->done_chdir;
814
815         *ctx_p = (struct conn_ctx) {
816                 .vuid = UID_FIELD_INVALID,
817         };
818 }
819
820 /****************************************************************************
821  Temporarily become a root user.  Must match with unbecome_root(). Saves and
822  restores the connection context.
823 ****************************************************************************/
824
825 void smbd_become_root(void)
826 {
827          /*
828           * no good way to handle push_sec_ctx() failing without changing
829           * the prototype of become_root()
830           */
831         if (!push_sec_ctx()) {
832                 smb_panic("become_root: push_sec_ctx failed");
833         }
834         push_conn_ctx();
835         set_root_sec_ctx();
836 }
837
838 /* Unbecome the root user */
839
840 void smbd_unbecome_root(void)
841 {
842         pop_sec_ctx();
843         pop_conn_ctx();
844 }
845
846 bool become_guest(void)
847 {
848         bool ok;
849
850         ok = push_sec_ctx();
851         if (!ok) {
852                 return false;
853         }
854
855         push_conn_ctx();
856
857         ok = change_to_guest();
858         if (!ok) {
859                 pop_sec_ctx();
860                 pop_conn_ctx();
861                 return false;
862         }
863
864         return true;
865 }
866
867 void unbecome_guest(void)
868 {
869         pop_sec_ctx();
870         pop_conn_ctx();
871         return;
872 }
873
874 /****************************************************************************
875  Push the current security context then force a change via change_to_user().
876  Saves and restores the connection context.
877 ****************************************************************************/
878
879 bool become_user(connection_struct *conn, uint64_t vuid)
880 {
881         if (!push_sec_ctx())
882                 return False;
883
884         push_conn_ctx();
885
886         if (!change_to_user(conn, vuid)) {
887                 pop_sec_ctx();
888                 pop_conn_ctx();
889                 return False;
890         }
891
892         return True;
893 }
894
895 bool become_user_by_fsp(struct files_struct *fsp)
896 {
897         return become_user(fsp->conn, fsp->vuid);
898 }
899
900 bool become_user_by_session(connection_struct *conn,
901                             const struct auth_session_info *session_info)
902 {
903         if (!push_sec_ctx())
904                 return false;
905
906         push_conn_ctx();
907
908         if (!change_to_user_by_session(conn, session_info)) {
909                 pop_sec_ctx();
910                 pop_conn_ctx();
911                 return false;
912         }
913
914         return true;
915 }
916
917 bool unbecome_user(void)
918 {
919         pop_sec_ctx();
920         pop_conn_ctx();
921         return True;
922 }
923
924 /****************************************************************************
925  Return the current user we are running effectively as on this connection.
926  I'd like to make this return conn->session_info->unix_token->uid, but become_root()
927  doesn't alter this value.
928 ****************************************************************************/
929
930 uid_t get_current_uid(connection_struct *conn)
931 {
932         return current_user.ut.uid;
933 }
934
935 /****************************************************************************
936  Return the current group we are running effectively as on this connection.
937  I'd like to make this return conn->session_info->unix_token->gid, but become_root()
938  doesn't alter this value.
939 ****************************************************************************/
940
941 gid_t get_current_gid(connection_struct *conn)
942 {
943         return current_user.ut.gid;
944 }
945
946 /****************************************************************************
947  Return the UNIX token we are running effectively as on this connection.
948  I'd like to make this return &conn->session_info->unix_token-> but become_root()
949  doesn't alter this value.
950 ****************************************************************************/
951
952 const struct security_unix_token *get_current_utok(connection_struct *conn)
953 {
954         return &current_user.ut;
955 }
956
957 /****************************************************************************
958  Return the Windows token we are running effectively as on this connection.
959  If this is currently a NULL token as we're inside become_root() - a temporary
960  UNIX security override, then we search up the stack for the previous active
961  token.
962 ****************************************************************************/
963
964 const struct security_token *get_current_nttok(connection_struct *conn)
965 {
966         if (current_user.nt_user_token) {
967                 return current_user.nt_user_token;
968         }
969         return sec_ctx_active_token();
970 }
971
972 uint64_t get_current_vuid(connection_struct *conn)
973 {
974         return current_user.vuid;
975 }
976
977 struct smbd_impersonate_conn_vuid_state {
978         struct connection_struct *conn;
979         uint64_t vuid;
980 };
981
982 static bool smbd_impersonate_conn_vuid_before_use(
983                 struct tevent_context *wrap_ev,
984                 void *private_data,
985                 struct tevent_context *main_ev,
986                 const char *location)
987 {
988         struct smbd_impersonate_conn_vuid_state *state =
989                 talloc_get_type_abort(private_data,
990                 struct smbd_impersonate_conn_vuid_state);
991         bool ok;
992
993         DEBUG(11,("%s: wrap_ev[%p] main_ev[%p] location[%s]"
994                   "old uid[%ju] old gid[%ju] vuid[%ju] cwd[%s]\n",
995                   __func__, wrap_ev, main_ev, location,
996                   (uintmax_t)geteuid(), (uintmax_t)getegid(),
997                   (uintmax_t)state->vuid, state->conn->cwd_fname->base_name));
998
999         ok = become_user(state->conn, state->vuid);
1000         if (!ok) {
1001                 smb_panic("smbd_impersonate_conn_vuid_before_use() - failed");
1002                 return false;
1003         }
1004
1005         DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1006                   __func__, state->conn->session_info->unix_info->unix_name,
1007                   (uintmax_t)geteuid(), (uintmax_t)getegid(),
1008                   state->conn->cwd_fname->base_name));
1009
1010         return true;
1011 }
1012
1013 static void smbd_impersonate_conn_vuid_after_use(
1014                 struct tevent_context *wrap_ev,
1015                 void *private_data,
1016                 struct tevent_context *main_ev,
1017                 const char *location)
1018 {
1019         struct smbd_impersonate_conn_vuid_state *state =
1020                 talloc_get_type_abort(private_data,
1021                 struct smbd_impersonate_conn_vuid_state);
1022         bool ok;
1023
1024         DEBUG(11,("%s: deimpersonating[%s] uid[%ju] gid[%ju] cwd[%s] "
1025                   "location[%s]\n",
1026                   __func__, state->conn->session_info->unix_info->unix_name,
1027                   (uintmax_t)geteuid(), (uintmax_t)getegid(),
1028                   state->conn->cwd_fname->base_name, location));
1029
1030         ok = unbecome_user();
1031         if (!ok) {
1032                 smb_panic("smbd_impersonate_conn_vuid_after_use() - failed");
1033                 return;
1034         }
1035
1036         DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1037                   __func__, state->conn->session_info->unix_info->unix_name,
1038                   (uintmax_t)geteuid(), (uintmax_t)getegid(),
1039                   state->conn->cwd_fname->base_name));
1040 }
1041
1042 static void smbd_impersonate_conn_vuid_before_fd_handler(
1043                 struct tevent_context *wrap_ev,
1044                 void *private_data,
1045                 struct tevent_context *main_ev,
1046                 struct tevent_fd *fde,
1047                 uint16_t flags,
1048                 const char *handler_name,
1049                 const char *location)
1050 {
1051         struct smbd_impersonate_conn_vuid_state *state = talloc_get_type_abort(
1052                 private_data, struct smbd_impersonate_conn_vuid_state);
1053         bool ok;
1054
1055         DEBUG(11,("%s: fde[%p] flags[%ju] handler_name[%s] location[%s]\n",
1056                   __func__, fde, (uintmax_t)flags, handler_name, location));
1057
1058         ok = change_to_user(state->conn, state->vuid);
1059         if (!ok) {
1060                 smb_panic("smbd_impersonate_conn_vuid_before_use() - failed");
1061                 return;
1062         }
1063
1064         DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1065                   __func__, state->conn->session_info->unix_info->unix_name,
1066                   (uintmax_t)geteuid(), (uintmax_t)getegid(),
1067                   state->conn->cwd_fname->base_name));
1068 }
1069
1070 static void smbd_impersonate_conn_vuid_after_fd_handler(
1071                 struct tevent_context *wrap_ev,
1072                 void *private_data,
1073                 struct tevent_context *main_ev,
1074                 struct tevent_fd *fde,
1075                 uint16_t flags,
1076                 const char *handler_name,
1077                 const char *location)
1078 {
1079         DEBUG(11,("%s: fde[%p] handler_name[%s] location[%s]\n",
1080                   __func__, fde, handler_name, location));
1081
1082         /* be lazy and defer change_to_root_user() */
1083 }
1084
1085 static void smbd_impersonate_conn_vuid_before_timer_handler(
1086                 struct tevent_context *wrap_ev,
1087                 void *private_data,
1088                 struct tevent_context *main_ev,
1089                 struct tevent_timer *te,
1090                 struct timeval requested_time,
1091                 struct timeval trigger_time,
1092                 const char *handler_name,
1093                 const char *location)
1094 {
1095         struct smbd_impersonate_conn_vuid_state *state = talloc_get_type_abort(
1096                 private_data, struct smbd_impersonate_conn_vuid_state);
1097         struct timeval_buf requested_buf;
1098         struct timeval_buf trigger_buf;
1099         bool ok;
1100
1101         DEBUG(11,("%s: te[%p] requested_time[%s] trigger_time[%s] "
1102                   "handler_name[%s] location[%s]\n",
1103                   __func__, te,
1104                   timeval_str_buf(&requested_time, true, true, &requested_buf),
1105                   timeval_str_buf(&trigger_time, true, true, &trigger_buf),
1106                   handler_name, location));
1107
1108         ok = change_to_user(state->conn, state->vuid);
1109         if (!ok) {
1110                 smb_panic("smbd_impersonate_conn_vuid_before_use() - failed");
1111                 return;
1112         }
1113
1114         DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1115                   __func__, state->conn->session_info->unix_info->unix_name,
1116                   (uintmax_t)geteuid(), (uintmax_t)getegid(),
1117                   state->conn->cwd_fname->base_name));
1118 }
1119
1120 static void smbd_impersonate_conn_vuid_after_timer_handler(
1121                 struct tevent_context *wrap_ev,
1122                 void *private_data,
1123                 struct tevent_context *main_ev,
1124                 struct tevent_timer *te,
1125                 struct timeval requested_time,
1126                 struct timeval trigger_time,
1127                 const char *handler_name,
1128                 const char *location)
1129 {
1130         DEBUG(11,("%s: te[%p] handler_name[%s] location[%s]\n",
1131                   __func__, te, handler_name, location));
1132
1133         /* be lazy and defer change_to_root_user() */
1134 }
1135
1136 static void smbd_impersonate_conn_vuid_before_immediate_handler(
1137                 struct tevent_context *wrap_ev,
1138                 void *private_data,
1139                 struct tevent_context *main_ev,
1140                 struct tevent_immediate *im,
1141                 const char *handler_name,
1142                 const char *location)
1143 {
1144         struct smbd_impersonate_conn_vuid_state *state = talloc_get_type_abort(
1145                 private_data, struct smbd_impersonate_conn_vuid_state);
1146         bool ok;
1147
1148         DEBUG(11,("%s: im[%p] handler_name[%s] location[%s]\n",
1149                   __func__, im, handler_name, location));
1150
1151         ok = change_to_user(state->conn, state->vuid);
1152         if (!ok) {
1153                 smb_panic("smbd_impersonate_conn_vuid_before_use() - failed");
1154                 return;
1155         }
1156
1157         DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1158                   __func__, state->conn->session_info->unix_info->unix_name,
1159                   (uintmax_t)geteuid(), (uintmax_t)getegid(),
1160                   state->conn->cwd_fname->base_name));
1161 }
1162
1163 static void smbd_impersonate_conn_vuid_after_immediate_handler(
1164                 struct tevent_context *wrap_ev,
1165                 void *private_data,
1166                 struct tevent_context *main_ev,
1167                 struct tevent_immediate *im,
1168                 const char *handler_name,
1169                 const char *location)
1170 {
1171         DEBUG(11,("%s: im[%p] handler_name[%s] location[%s]\n",
1172                   __func__, im, handler_name, location));
1173
1174         /* be lazy and defer unbecome_user() */
1175 }
1176
1177 static void smbd_impersonate_conn_vuid_before_signal_handler(
1178                 struct tevent_context *wrap_ev,
1179                 void *private_data,
1180                 struct tevent_context *main_ev,
1181                 struct tevent_signal *se,
1182                 int signum,
1183                 int count,
1184                 void *siginfo,
1185                 const char *handler_name,
1186                 const char *location)
1187 {
1188         struct smbd_impersonate_conn_vuid_state *state = talloc_get_type_abort(
1189                 private_data, struct smbd_impersonate_conn_vuid_state);
1190         bool ok;
1191
1192         DEBUG(11,("%s: se[%p] signum[%d] count[%d] siginfo[%p] "
1193                   "handler_name[%s] location[%s]\n",
1194                   __func__, se, signum, count, siginfo, handler_name, location));
1195
1196         ok = change_to_user(state->conn, state->vuid);
1197         if (!ok) {
1198                 smb_panic("smbd_impersonate_conn_vuid_before_use() - failed");
1199                 return;
1200         }
1201
1202         DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1203                   __func__, state->conn->session_info->unix_info->unix_name,
1204                   (uintmax_t)geteuid(), (uintmax_t)getegid(),
1205                   state->conn->cwd_fname->base_name));
1206 }
1207
1208 static void smbd_impersonate_conn_vuid_after_signal_handler(
1209                 struct tevent_context *wrap_ev,
1210                 void *private_data,
1211                 struct tevent_context *main_ev,
1212                 struct tevent_signal *se,
1213                 int signum,
1214                 int count,
1215                 void *siginfo,
1216                 const char *handler_name,
1217                 const char *location)
1218 {
1219         DEBUG(11,("%s: se[%p] handler_name[%s] location[%s]\n",
1220                   __func__, se, handler_name, location));
1221
1222         /* be lazy and defer change_to_root_user() */
1223 }
1224
1225 static const struct tevent_wrapper_ops smbd_impersonate_conn_vuid_ops = {
1226         .name                           = "smbd_impersonate_conn_vuid",
1227         .before_use                     = smbd_impersonate_conn_vuid_before_use,
1228         .after_use                      = smbd_impersonate_conn_vuid_after_use,
1229         .before_fd_handler              = smbd_impersonate_conn_vuid_before_fd_handler,
1230         .after_fd_handler               = smbd_impersonate_conn_vuid_after_fd_handler,
1231         .before_timer_handler           = smbd_impersonate_conn_vuid_before_timer_handler,
1232         .after_timer_handler            = smbd_impersonate_conn_vuid_after_timer_handler,
1233         .before_immediate_handler       = smbd_impersonate_conn_vuid_before_immediate_handler,
1234         .after_immediate_handler        = smbd_impersonate_conn_vuid_after_immediate_handler,
1235         .before_signal_handler          = smbd_impersonate_conn_vuid_before_signal_handler,
1236         .after_signal_handler           = smbd_impersonate_conn_vuid_after_signal_handler,
1237 };
1238
1239 struct tevent_context *smbd_impersonate_conn_vuid_create(
1240                                 struct tevent_context *main_ev,
1241                                 struct connection_struct *conn,
1242                                 uint64_t vuid)
1243 {
1244         struct tevent_context *ev = NULL;
1245         struct smbd_impersonate_conn_vuid_state *state = NULL;
1246
1247         ev = tevent_context_wrapper_create(main_ev,
1248                                            conn,
1249                                            &smbd_impersonate_conn_vuid_ops,
1250                                            &state,
1251                                            struct smbd_impersonate_conn_vuid_state);
1252         if (ev == NULL) {
1253                 return NULL;
1254         }
1255         state->conn = conn;
1256         state->vuid = vuid;
1257
1258         return ev;
1259 }
1260
1261 struct smbd_impersonate_conn_sess_state {
1262         struct connection_struct *conn;
1263         struct auth_session_info *session_info;
1264 };
1265
1266 static bool smbd_impersonate_conn_sess_before_use(struct tevent_context *wrap_ev,
1267                                                   void *private_data,
1268                                                   struct tevent_context *main_ev,
1269                                                   const char *location)
1270 {
1271         struct smbd_impersonate_conn_sess_state *state = talloc_get_type_abort(
1272                 private_data, struct smbd_impersonate_conn_sess_state);
1273         bool ok;
1274
1275         DEBUG(11,("%s: impersonating user[%s] wrap_ev[%p] main_ev[%p] "
1276                   "location[%s] old uid[%ju] old gid[%ju] cwd[%s]\n",
1277                   __func__, state->session_info->unix_info->unix_name,
1278                   wrap_ev, main_ev, location,
1279                   (uintmax_t)geteuid(), (uintmax_t)getegid(),
1280                   state->conn->cwd_fname->base_name));
1281
1282         ok = become_user_by_session(state->conn, state->session_info);
1283         if (!ok) {
1284                 return false;
1285         }
1286
1287         DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1288                   __func__, state->conn->session_info->unix_info->unix_name,
1289                   (uintmax_t)geteuid(), (uintmax_t)getegid(),
1290                   state->conn->cwd_fname->base_name));
1291
1292         return true;
1293 }
1294
1295 static void smbd_impersonate_conn_sess_after_use(struct tevent_context *wrap_ev,
1296                                                  void *private_data,
1297                                                  struct tevent_context *main_ev,
1298                                                  const char *location)
1299 {
1300         struct smbd_impersonate_conn_sess_state *state = talloc_get_type_abort(
1301                 private_data, struct smbd_impersonate_conn_sess_state);
1302         bool ok;
1303
1304         DEBUG(11,("%s: deimpersonating[%s] uid[%ju] gid[%ju] cwd[%s] "
1305                   "location[%s]\n",
1306                   __func__, state->session_info->unix_info->unix_name,
1307                   (uintmax_t)geteuid(), (uintmax_t)getegid(),
1308                   state->conn->cwd_fname->base_name, location));
1309
1310         ok = unbecome_user();
1311         if (!ok) {
1312                 smb_panic("smbd_impersonate_conn_sess_after_use() - failed");
1313                 return;
1314         }
1315
1316         DEBUG(11,("%s: deimpersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1317                   __func__, state->conn->session_info->unix_info->unix_name,
1318                   (uintmax_t)geteuid(), (uintmax_t)getegid(),
1319                   state->conn->cwd_fname->base_name));
1320 }
1321
1322 static void smbd_impersonate_conn_sess_before_fd_handler(
1323                 struct tevent_context *wrap_ev,
1324                 void *private_data,
1325                 struct tevent_context *main_ev,
1326                 struct tevent_fd *fde,
1327                 uint16_t flags,
1328                 const char *handler_name,
1329                 const char *location)
1330 {
1331         struct smbd_impersonate_conn_sess_state *state = talloc_get_type_abort(
1332                 private_data, struct smbd_impersonate_conn_sess_state);
1333         bool ok;
1334
1335         DEBUG(11,("%s: fde[%p] flags[%ju] handler_name[%s] location[%s]\n",
1336                   __func__, fde, (uintmax_t)flags, handler_name, location));
1337
1338         ok = change_to_user_by_session(state->conn, state->session_info);
1339         if (!ok) {
1340                 smb_panic("smbd_impersonate_conn_sess_before_fd_handler failed");
1341                 return;
1342         }
1343
1344         DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1345                   __func__, state->conn->session_info->unix_info->unix_name,
1346                   (uintmax_t)geteuid(), (uintmax_t)getegid(),
1347                   state->conn->cwd_fname->base_name));
1348 }
1349
1350 static void smbd_impersonate_conn_sess_after_fd_handler(struct tevent_context *wrap_ev,
1351                                                         void *private_data,
1352                                                         struct tevent_context *main_ev,
1353                                                         struct tevent_fd *fde,
1354                                                         uint16_t flags,
1355                                                         const char *handler_name,
1356                                                         const char *location)
1357 {
1358         DEBUG(11,("%s: fde[%p] handler_name[%s] location[%s]\n",
1359                   __func__, fde, handler_name, location));
1360
1361         /* be lazy and defer change_to_root_user() */
1362 }
1363
1364 static void smbd_impersonate_conn_sess_before_timer_handler(
1365                 struct tevent_context *wrap_ev,
1366                 void *private_data,
1367                 struct tevent_context *main_ev,
1368                 struct tevent_timer *te,
1369                 struct timeval requested_time,
1370                 struct timeval trigger_time,
1371                 const char *handler_name,
1372                 const char *location)
1373 {
1374         struct smbd_impersonate_conn_sess_state *state = talloc_get_type_abort(
1375                 private_data, struct smbd_impersonate_conn_sess_state);
1376         struct timeval_buf requested_buf;
1377         struct timeval_buf trigger_buf;
1378         bool ok;
1379
1380         DEBUG(11,("%s: te[%p] requested_time[%s] trigger_time[%s] "
1381                   "handler_name[%s] location[%s]\n",
1382                   __func__, te,
1383                   timeval_str_buf(&requested_time, true, true, &requested_buf),
1384                   timeval_str_buf(&trigger_time, true, true, &trigger_buf),
1385                   handler_name, location));
1386
1387         ok = change_to_user_by_session(state->conn, state->session_info);
1388         if (!ok) {
1389                 smb_panic("smbd_impersonate_conn_sess_before_tm_handler failed");
1390                 return;
1391         }
1392
1393         DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1394                   __func__, state->conn->session_info->unix_info->unix_name,
1395                   (uintmax_t)geteuid(), (uintmax_t)getegid(),
1396                   state->conn->cwd_fname->base_name));
1397 }
1398
1399 static void smbd_impersonate_conn_sess_after_timer_handler(
1400                 struct tevent_context *wrap_ev,
1401                 void *private_data,
1402                 struct tevent_context *main_ev,
1403                 struct tevent_timer *te,
1404                 struct timeval requested_time,
1405                 struct timeval trigger_time,
1406                 const char *handler_name,
1407                 const char *location)
1408 {
1409         DEBUG(11,("%s: te[%p] handler_name[%s] location[%s]\n",
1410                   __func__, te, handler_name, location));
1411
1412         /* be lazy and defer change_to_root_user() */
1413 }
1414
1415 static void smbd_impersonate_conn_sess_before_immediate_handler(
1416                 struct tevent_context *wrap_ev,
1417                 void *private_data,
1418                 struct tevent_context *main_ev,
1419                 struct tevent_immediate *im,
1420                 const char *handler_name,
1421                 const char *location)
1422 {
1423         struct smbd_impersonate_conn_sess_state *state = talloc_get_type_abort(
1424                 private_data, struct smbd_impersonate_conn_sess_state);
1425         bool ok;
1426
1427         DEBUG(11,("%s: im[%p] handler_name[%s] location[%s]\n",
1428                   __func__, im, handler_name, location));
1429
1430         ok = change_to_user_by_session(state->conn, state->session_info);
1431         if (!ok) {
1432                 smb_panic("smbd_impersonate_conn_sess_before_im_handler failed");
1433                 return;
1434         }
1435
1436         DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1437                   __func__, state->conn->session_info->unix_info->unix_name,
1438                   (uintmax_t)geteuid(), (uintmax_t)getegid(),
1439                   state->conn->cwd_fname->base_name));
1440 }
1441
1442 static void smbd_impersonate_conn_sess_after_immediate_handler(
1443                 struct tevent_context *wrap_ev,
1444                 void *private_data,
1445                 struct tevent_context *main_ev,
1446                 struct tevent_immediate *im,
1447                 const char *handler_name,
1448                 const char *location)
1449 {
1450         DEBUG(11,("%s: im[%p] handler_name[%s] location[%s]\n",
1451                   __func__, im, handler_name, location));
1452
1453         /* be lazy and defer unbecome_user() */
1454 }
1455
1456 static void smbd_impersonate_conn_sess_before_signal_handler(
1457                 struct tevent_context *wrap_ev,
1458                 void *private_data,
1459                 struct tevent_context *main_ev,
1460                 struct tevent_signal *se,
1461                 int signum,
1462                 int count,
1463                 void *siginfo,
1464                 const char *handler_name,
1465                 const char *location)
1466 {
1467         struct smbd_impersonate_conn_sess_state *state = talloc_get_type_abort(
1468                 private_data, struct smbd_impersonate_conn_sess_state);
1469         bool ok;
1470
1471         DEBUG(11,("%s: se[%p] signum[%d] count[%d] siginfo[%p] "
1472                   "handler_name[%s] location[%s]\n",
1473                   __func__, se, signum, count, siginfo, handler_name, location));
1474
1475         ok = change_to_user_by_session(state->conn, state->session_info);
1476         if (!ok) {
1477                 smb_panic("smbd_impersonate_conn_sess_before_si_handler failed");
1478                 return;
1479         }
1480
1481         DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
1482                   __func__, state->conn->session_info->unix_info->unix_name,
1483                   (uintmax_t)geteuid(), (uintmax_t)getegid(),
1484                   state->conn->cwd_fname->base_name));
1485 }
1486
1487 static void smbd_impersonate_conn_sess_after_signal_handler(
1488                 struct tevent_context *wrap_ev,
1489                 void *private_data,
1490                 struct tevent_context *main_ev,
1491                 struct tevent_signal *se,
1492                 int signum,
1493                 int count,
1494                 void *siginfo,
1495                 const char *handler_name,
1496                 const char *location)
1497 {
1498         DEBUG(11,("%s: se[%p] handler_name[%s] location[%s]\n",
1499                   __func__, se, handler_name, location));
1500
1501         /* be lazy and defer change_to_root_user() */
1502 }
1503
1504 static const struct tevent_wrapper_ops smbd_impersonate_conn_sess_ops = {
1505         .name                           = "smbd_impersonate_conn_sess",
1506         .before_use                     = smbd_impersonate_conn_sess_before_use,
1507         .after_use                      = smbd_impersonate_conn_sess_after_use,
1508         .before_fd_handler              = smbd_impersonate_conn_sess_before_fd_handler,
1509         .after_fd_handler               = smbd_impersonate_conn_sess_after_fd_handler,
1510         .before_timer_handler           = smbd_impersonate_conn_sess_before_timer_handler,
1511         .after_timer_handler            = smbd_impersonate_conn_sess_after_timer_handler,
1512         .before_immediate_handler       = smbd_impersonate_conn_sess_before_immediate_handler,
1513         .after_immediate_handler        = smbd_impersonate_conn_sess_after_immediate_handler,
1514         .before_signal_handler          = smbd_impersonate_conn_sess_before_signal_handler,
1515         .after_signal_handler           = smbd_impersonate_conn_sess_after_signal_handler,
1516 };
1517
1518 struct tevent_context *smbd_impersonate_conn_sess_create(
1519                                 struct tevent_context *main_ev,
1520                                 struct connection_struct *conn,
1521                                 struct auth_session_info *session_info)
1522 {
1523         struct tevent_context *ev = NULL;
1524         struct smbd_impersonate_conn_sess_state *state = NULL;
1525
1526         ev = tevent_context_wrapper_create(main_ev,
1527                                            conn,
1528                                            &smbd_impersonate_conn_sess_ops,
1529                                            &state,
1530                                            struct smbd_impersonate_conn_sess_state);
1531         if (ev == NULL) {
1532                 return NULL;
1533         }
1534         state->conn = conn;
1535         state->session_info = session_info;
1536
1537         return ev;
1538 }
1539
1540 struct smbd_impersonate_root_state {
1541         uint8_t _dummy;
1542 };
1543
1544 static bool smbd_impersonate_root_before_use(struct tevent_context *wrap_ev,
1545                                              void *private_data,
1546                                              struct tevent_context *main_ev,
1547                                              const char *location)
1548 {
1549         DEBUG(11,("%s: wrap_ev[%p] main_ev[%p] location[%s]"
1550                   "uid[%ju] gid[%ju]\n",
1551                   __func__, wrap_ev, main_ev, location,
1552                   (uintmax_t)geteuid(), (uintmax_t)getegid()));
1553
1554         become_root();
1555         return true;
1556 }
1557
1558 static void smbd_impersonate_root_after_use(struct tevent_context *wrap_ev,
1559                                             void *private_data,
1560                                             struct tevent_context *main_ev,
1561                                             const char *location)
1562 {
1563         unbecome_root();
1564
1565         DEBUG(11,("%s: uid[%ju] gid[%ju] location[%s]\n",
1566                   __func__, (uintmax_t)geteuid(), (uintmax_t)getegid(),
1567                   location));
1568 }
1569
1570 static void smbd_impersonate_root_before_fd_handler(struct tevent_context *wrap_ev,
1571                                                 void *private_data,
1572                                                 struct tevent_context *main_ev,
1573                                                 struct tevent_fd *fde,
1574                                                 uint16_t flags,
1575                                                 const char *handler_name,
1576                                                 const char *location)
1577 {
1578         DEBUG(11,("%s: fde[%p] flags[%ju] handler_name[%s] location[%s]\n",
1579                   __func__, fde, (uintmax_t)flags, handler_name, location));
1580
1581         smbd_impersonate_root_before_use(wrap_ev, private_data, main_ev, location);
1582 }
1583
1584 static void smbd_impersonate_root_after_fd_handler(struct tevent_context *wrap_ev,
1585                                                 void *private_data,
1586                                                 struct tevent_context *main_ev,
1587                                                 struct tevent_fd *fde,
1588                                                 uint16_t flags,
1589                                                 const char *handler_name,
1590                                                 const char *location)
1591 {
1592         DEBUG(11,("%s: fde[%p] handler_name[%s] location[%s]\n",
1593                   __func__, fde, handler_name, location));
1594
1595         smbd_impersonate_root_after_use(wrap_ev, private_data, main_ev, location);
1596 }
1597
1598 static void smbd_impersonate_root_before_timer_handler(struct tevent_context *wrap_ev,
1599                                                 void *private_data,
1600                                                 struct tevent_context *main_ev,
1601                                                 struct tevent_timer *te,
1602                                                 struct timeval requested_time,
1603                                                 struct timeval trigger_time,
1604                                                 const char *handler_name,
1605                                                 const char *location)
1606 {
1607         struct timeval_buf requested_buf;
1608         struct timeval_buf trigger_buf;
1609
1610         DEBUG(11,("%s: te[%p] requested_time[%s] trigger_time[%s] "
1611                   "handler_name[%s] location[%s]\n",
1612                   __func__, te,
1613                   timeval_str_buf(&requested_time, true, true, &requested_buf),
1614                   timeval_str_buf(&trigger_time, true, true, &trigger_buf),
1615                   handler_name, location));
1616
1617         smbd_impersonate_root_before_use(wrap_ev, private_data, main_ev, location);
1618 }
1619
1620 static void smbd_impersonate_root_after_timer_handler(struct tevent_context *wrap_ev,
1621                                                 void *private_data,
1622                                                 struct tevent_context *main_ev,
1623                                                 struct tevent_timer *te,
1624                                                 struct timeval requested_time,
1625                                                 struct timeval trigger_time,
1626                                                 const char *handler_name,
1627                                                 const char *location)
1628 {
1629         DEBUG(11,("%s: te[%p] handler_name[%s] location[%s]\n",
1630                   __func__, te, handler_name, location));
1631
1632         smbd_impersonate_root_after_use(wrap_ev, private_data, main_ev, location);
1633 }
1634
1635 static void smbd_impersonate_root_before_immediate_handler(struct tevent_context *wrap_ev,
1636                                                 void *private_data,
1637                                                 struct tevent_context *main_ev,
1638                                                 struct tevent_immediate *im,
1639                                                 const char *handler_name,
1640                                                 const char *location)
1641 {
1642         DEBUG(11,("%s: im[%p] handler_name[%s] location[%s]\n",
1643                   __func__, im, handler_name, location));
1644
1645         smbd_impersonate_root_before_use(wrap_ev, private_data, main_ev, location);
1646 }
1647
1648 static void smbd_impersonate_root_after_immediate_handler(struct tevent_context *wrap_ev,
1649                                                 void *private_data,
1650                                                 struct tevent_context *main_ev,
1651                                                 struct tevent_immediate *im,
1652                                                 const char *handler_name,
1653                                                 const char *location)
1654 {
1655         DEBUG(11,("%s: im[%p] handler_name[%s] location[%s]\n",
1656                   __func__, im, handler_name, location));
1657
1658         smbd_impersonate_root_after_use(wrap_ev, private_data, main_ev, location);
1659 }
1660
1661 static void smbd_impersonate_root_before_signal_handler(struct tevent_context *wrap_ev,
1662                                                 void *private_data,
1663                                                 struct tevent_context *main_ev,
1664                                                 struct tevent_signal *se,
1665                                                 int signum,
1666                                                 int count,
1667                                                 void *siginfo,
1668                                                 const char *handler_name,
1669                                                 const char *location)
1670 {
1671         DEBUG(11,("%s: se[%p] signum[%d] count[%d] siginfo[%p] "
1672                   "handler_name[%s] location[%s]\n",
1673                   __func__, se, signum, count, siginfo, handler_name, location));
1674
1675         smbd_impersonate_root_before_use(wrap_ev, private_data, main_ev, location);
1676 }
1677
1678 static void smbd_impersonate_root_after_signal_handler(struct tevent_context *wrap_ev,
1679                                                 void *private_data,
1680                                                 struct tevent_context *main_ev,
1681                                                 struct tevent_signal *se,
1682                                                 int signum,
1683                                                 int count,
1684                                                 void *siginfo,
1685                                                 const char *handler_name,
1686                                                 const char *location)
1687 {
1688         DEBUG(11,("%s: se[%p] handler_name[%s] location[%s]\n",
1689                   __func__, se, handler_name, location));
1690
1691         smbd_impersonate_root_after_use(wrap_ev, private_data, main_ev, location);
1692 }
1693
1694 static const struct tevent_wrapper_ops smbd_impersonate_root_ops = {
1695         .name                           = "smbd_impersonate_root",
1696         .before_use                     = smbd_impersonate_root_before_use,
1697         .after_use                      = smbd_impersonate_root_after_use,
1698         .before_fd_handler              = smbd_impersonate_root_before_fd_handler,
1699         .after_fd_handler               = smbd_impersonate_root_after_fd_handler,
1700         .before_timer_handler           = smbd_impersonate_root_before_timer_handler,
1701         .after_timer_handler            = smbd_impersonate_root_after_timer_handler,
1702         .before_immediate_handler       = smbd_impersonate_root_before_immediate_handler,
1703         .after_immediate_handler        = smbd_impersonate_root_after_immediate_handler,
1704         .before_signal_handler          = smbd_impersonate_root_before_signal_handler,
1705         .after_signal_handler           = smbd_impersonate_root_after_signal_handler,
1706 };
1707
1708 struct tevent_context *smbd_impersonate_root_create(struct tevent_context *main_ev)
1709 {
1710         struct tevent_context *ev = NULL;
1711         struct smbd_impersonate_root_state *state = NULL;
1712
1713         ev = tevent_context_wrapper_create(main_ev,
1714                                            main_ev,
1715                                            &smbd_impersonate_root_ops,
1716                                            &state,
1717                                            struct smbd_impersonate_root_state);
1718         if (ev == NULL) {
1719                 return NULL;
1720         }
1721
1722         return ev;
1723 }
1724
1725 struct smbd_impersonate_guest_state {
1726         uint8_t _dummy;
1727 };
1728
1729 static bool smbd_impersonate_guest_before_use(struct tevent_context *wrap_ev,
1730                                               void *private_data,
1731                                               struct tevent_context *main_ev,
1732                                               const char *location)
1733 {
1734         DEBUG(11,("%s: wrap_ev[%p] main_ev[%p] location[%s]"
1735                   "uid[%ju] gid[%ju]\n",
1736                   __func__, wrap_ev, main_ev, location,
1737                   (uintmax_t)geteuid(), (uintmax_t)getegid()));
1738
1739         return become_guest();
1740 }
1741
1742 static void smbd_impersonate_guest_after_use(struct tevent_context *wrap_ev,
1743                                              void *private_data,
1744                                              struct tevent_context *main_ev,
1745                                              const char *location)
1746 {
1747         unbecome_guest();
1748
1749         DEBUG(11,("%s: uid[%ju] gid[%ju] location[%s]\n",
1750                   __func__, (uintmax_t)geteuid(), (uintmax_t)getegid(),
1751                   location));
1752 }
1753
1754 static void smbd_impersonate_guest_before_fd_handler(struct tevent_context *wrap_ev,
1755                                                 void *private_data,
1756                                                 struct tevent_context *main_ev,
1757                                                 struct tevent_fd *fde,
1758                                                 uint16_t flags,
1759                                                 const char *handler_name,
1760                                                 const char *location)
1761 {
1762         bool ok;
1763
1764         DEBUG(11,("%s: fde[%p] flags[%ju] handler_name[%s] location[%s]\n",
1765                   __func__, fde, (uintmax_t)flags, handler_name, location));
1766
1767         ok = smbd_impersonate_guest_before_use(wrap_ev, private_data,
1768                                                 main_ev, location);
1769         if (!ok) {
1770                 smb_panic("smbd_impersonate_guest_before_use() - failed");
1771                 return;
1772         }
1773 }
1774
1775 static void smbd_impersonate_guest_after_fd_handler(struct tevent_context *wrap_ev,
1776                                                 void *private_data,
1777                                                 struct tevent_context *main_ev,
1778                                                 struct tevent_fd *fde,
1779                                                 uint16_t flags,
1780                                                 const char *handler_name,
1781                                                 const char *location)
1782 {
1783         DEBUG(11,("%s: fde[%p] handler_name[%s] location[%s]\n",
1784                   __func__, fde, handler_name, location));
1785
1786         smbd_impersonate_guest_after_use(wrap_ev, private_data, main_ev, location);
1787 }
1788
1789 static void smbd_impersonate_guest_before_timer_handler(struct tevent_context *wrap_ev,
1790                                                 void *private_data,
1791                                                 struct tevent_context *main_ev,
1792                                                 struct tevent_timer *te,
1793                                                 struct timeval requested_time,
1794                                                 struct timeval trigger_time,
1795                                                 const char *handler_name,
1796                                                 const char *location)
1797 {
1798         bool ok;
1799         struct timeval_buf requested_buf;
1800         struct timeval_buf trigger_buf;
1801
1802         DEBUG(11,("%s: te[%p] requested_time[%s] trigger_time[%s] "
1803                   "handler_name[%s] location[%s]\n",
1804                   __func__, te,
1805                   timeval_str_buf(&requested_time, true, true, &requested_buf),
1806                   timeval_str_buf(&trigger_time, true, true, &trigger_buf),
1807                   handler_name, location));
1808
1809         ok = smbd_impersonate_guest_before_use(wrap_ev, private_data,
1810                                                main_ev, location);
1811         if (!ok) {
1812                 smb_panic("smbd_impersonate_guest_before_use() - failed");
1813                 return;
1814         }
1815 }
1816
1817 static void smbd_impersonate_guest_after_timer_handler(struct tevent_context *wrap_ev,
1818                                                 void *private_data,
1819                                                 struct tevent_context *main_ev,
1820                                                 struct tevent_timer *te,
1821                                                 struct timeval requested_time,
1822                                                 struct timeval trigger_time,
1823                                                 const char *handler_name,
1824                                                 const char *location)
1825 {
1826         DEBUG(11,("%s: te[%p] handler_name[%s] location[%s]\n",
1827                   __func__, te, handler_name, location));
1828
1829         smbd_impersonate_guest_after_use(wrap_ev, private_data, main_ev, location);
1830 }
1831
1832 static void smbd_impersonate_guest_before_immediate_handler(struct tevent_context *wrap_ev,
1833                                                 void *private_data,
1834                                                 struct tevent_context *main_ev,
1835                                                 struct tevent_immediate *im,
1836                                                 const char *handler_name,
1837                                                 const char *location)
1838 {
1839         bool ok;
1840
1841         DEBUG(11,("%s: im[%p] handler_name[%s] location[%s]\n",
1842                   __func__, im, handler_name, location));
1843
1844         ok = smbd_impersonate_guest_before_use(wrap_ev, private_data,
1845                                                main_ev, location);
1846         if (!ok) {
1847                 smb_panic("smbd_impersonate_guest_before_use() - failed");
1848                 return;
1849         }
1850 }
1851
1852 static void smbd_impersonate_guest_after_immediate_handler(struct tevent_context *wrap_ev,
1853                                                 void *private_data,
1854                                                 struct tevent_context *main_ev,
1855                                                 struct tevent_immediate *im,
1856                                                 const char *handler_name,
1857                                                 const char *location)
1858 {
1859         DEBUG(11,("%s: im[%p] handler_name[%s] location[%s]\n",
1860                   __func__, im, handler_name, location));
1861
1862         smbd_impersonate_guest_after_use(wrap_ev, private_data, main_ev, location);
1863 }
1864
1865 static void smbd_impersonate_guest_before_signal_handler(struct tevent_context *wrap_ev,
1866                                                 void *private_data,
1867                                                 struct tevent_context *main_ev,
1868                                                 struct tevent_signal *se,
1869                                                 int signum,
1870                                                 int count,
1871                                                 void *siginfo,
1872                                                 const char *handler_name,
1873                                                 const char *location)
1874 {
1875         bool ok;
1876
1877         DEBUG(11,("%s: se[%p] signum[%d] count[%d] siginfo[%p] "
1878                   "handler_name[%s] location[%s]\n",
1879                   __func__, se, signum, count, siginfo, handler_name, location));
1880
1881         ok = smbd_impersonate_guest_before_use(wrap_ev, private_data,
1882                                                main_ev, location);
1883         if (!ok) {
1884                 smb_panic("smbd_impersonate_guest_before_use() - failed");
1885                 return;
1886         }
1887 }
1888
1889 static void smbd_impersonate_guest_after_signal_handler(struct tevent_context *wrap_ev,
1890                                                 void *private_data,
1891                                                 struct tevent_context *main_ev,
1892                                                 struct tevent_signal *se,
1893                                                 int signum,
1894                                                 int count,
1895                                                 void *siginfo,
1896                                                 const char *handler_name,
1897                                                 const char *location)
1898 {
1899         DEBUG(11,("%s: se[%p] handler_name[%s] location[%s]\n",
1900                   __func__, se, handler_name, location));
1901
1902         smbd_impersonate_guest_after_use(wrap_ev, private_data, main_ev, location);
1903 }
1904
1905 static const struct tevent_wrapper_ops smbd_impersonate_guest_ops = {
1906         .name                           = "smbd_impersonate_guest",
1907         .before_use                     = smbd_impersonate_guest_before_use,
1908         .after_use                      = smbd_impersonate_guest_after_use,
1909         .before_fd_handler              = smbd_impersonate_guest_before_fd_handler,
1910         .after_fd_handler               = smbd_impersonate_guest_after_fd_handler,
1911         .before_timer_handler           = smbd_impersonate_guest_before_timer_handler,
1912         .after_timer_handler            = smbd_impersonate_guest_after_timer_handler,
1913         .before_immediate_handler       = smbd_impersonate_guest_before_immediate_handler,
1914         .after_immediate_handler        = smbd_impersonate_guest_after_immediate_handler,
1915         .before_signal_handler          = smbd_impersonate_guest_before_signal_handler,
1916         .after_signal_handler           = smbd_impersonate_guest_after_signal_handler,
1917 };
1918
1919 struct tevent_context *smbd_impersonate_guest_create(struct tevent_context *main_ev)
1920 {
1921         struct tevent_context *ev = NULL;
1922         struct smbd_impersonate_guest_state *state = NULL;
1923
1924         ev = tevent_context_wrapper_create(main_ev,
1925                                            main_ev,
1926                                            &smbd_impersonate_guest_ops,
1927                                            &state,
1928                                            struct smbd_impersonate_guest_state);
1929         if (ev == NULL) {
1930                 return NULL;
1931         }
1932
1933         return ev;
1934 }