From edf045d4f1d434396d50043d1ebeec5ef31b7068 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 11 May 2012 15:51:42 +0200 Subject: [PATCH] start source3/smbd/tevent_impersonate.c --- source3/smbd/service.c | 3 + source3/smbd/tevent_impersonate.c | 526 ++++++++++++++++++++++++++++++ 2 files changed, 529 insertions(+) create mode 100644 source3/smbd/tevent_impersonate.c diff --git a/source3/smbd/service.c b/source3/smbd/service.c index d0fd215dc7ee..d875c3afb23e 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -656,6 +656,9 @@ static NTSTATUS make_connection_snum(struct smbd_server_connection *sconn, } /* Initialise VFS function pointers */ +//tevent_impersonate_create_context +//conn->ev_ctx, + if (!smbd_vfs_init(conn)) { DEBUG(0, ("vfs_init failed for service %s\n", lp_servicename(snum))); diff --git a/source3/smbd/tevent_impersonate.c b/source3/smbd/tevent_impersonate.c new file mode 100644 index 000000000000..c12027bae04f --- /dev/null +++ b/source3/smbd/tevent_impersonate.c @@ -0,0 +1,526 @@ +/* + Unix SMB/CIFS implementation. + async uid/user handling + Copyright (C) Stefan Metzmacher 2012 + Copyright (C) David Disseldorp 2012 + Copyright (C) Michael Adam 2012 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include +//#include "lib/tevent/tevent_internal.h" +//#include "../lib/util/select.h" +//#include "system/select.h" + +struct tevent_impersonate_context { + struct tevent_context *main_ev; + struct connection_struct *conn; + uint64_t vuid; +}; + +static int tevent_impersonate_init(struct tevent_context *ev) +{ + struct tevent_impersonate_context *a = + talloc_get_type_abort(ev->additional_data, + struct tevent_impersonate_context); + + talloc_steal(ev, a); + + return 0; +} + +static void tevent_impersonate_become_context(struct tevent_context *ev) +{ + struct tevent_impersonate_context *a = + talloc_get_type_abort(ev->additional_data, + struct tevent_impersonate_context); + + if (a->conn) { + ok = change_to_user(a->conn, a->vuid); + //TODO + set_current_service(a->conn, 0, true); + } else { + ok = change_to_root_user(); + } +} + + +/* + * tevent_impersonate_add_fd + */ + +static void tevent_impersonate_fd_handler(struct tevent_context *main_ev, + struct tevent_fd *main_fde, + uint16_t flags, + void *private_data); + +struct tevent_fd *tevent_impersonate_add_fd(struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + int fd, uint16_t flags, + tevent_fd_handler_t handler, + void *private_data, + const char *handler_name, + const char *location) +{ + struct tevent_impersonate_context *a = + talloc_get_type_abort(ev->additional_data, + struct tevent_impersonate_context); + struct tevent_context *main_ev = a->main_ev; + struct tevent_fd *fde; + + /* tevent will crash later on select() if we save + * a negative file descriptor. Better to fail here + * so that consumers will be able to debug it + */ + if (fd < 0) return NULL; + + fde = talloc(mem_ctx?mem_ctx:ev, struct tevent_fd); + if (!fde) return NULL; // TODO: ugly formatting... + + fde->event_ctx = ev; + fde->fd = fd; + fde->flags = flags; + fde->handler = handler; + fde->close_fn = NULL; + fde->private_data = private_data; + fde->handler_name = handler_name; + fde->location = location; + fde->additional_flags = 0; + fde->additional_data = NULL; + + main_fde = _tevent_add_fd(main_ev, fde, fd, flags, + tevent_impersonate_fd_handler, fde, + handler_name, location); + if (main_fde == NULL) { + talloc_free(fde); + return NULL; + } + + fde->additional_data = main_fde; + + return fde; +} + +static void tevent_impersonate_fd_handler(struct tevent_context *main_ev, + struct tevent_fd *main_fde, + uint16_t flags, + void *private_data) +{ + struct tevent_fd *fde = + talloc_get_type_abort(private_data, + struct tevent_fd); + struct tevent_context *ev = fde->ev; + + tevent_impersonate_become_context(ev); + fde->handler(ev, fde, fde->flags, fde->private_data); +} + + +/* + * tevent_impersonate_fd_set_close_fn + */ +static void tevent_impersonate_fd_set_close_fn(struct tevent_fd *fde, + tevent_fd_close_fn_t close_fn) +{ + struct tevent_f *main_fde = + talloc_get_type_abort(fde->additional_data, + struct tevent_fd); + + main_fde->close_fn = close_fn; +} + + +/* + * tevent_impersonate_fd_get_flags + */ +static uint16_t tevent_impersonate_fd_get_flags(struct tevent_fd *fde) +{ + struct tevent_f *main_fde = + talloc_get_type_abort(fde->additional_data, + struct tevent_fd); + + return tevent_fd_get_flags(fde); +} + + +/* + * tevent_impersonate_fd_set_flags + */ +static void tevent_impersonate_fd_set_flags(struct tevent_fd *fde, + uint16_t flags) +{ + struct tevent_f *main_fde = + talloc_get_type_abort(fde->additional_data, + struct tevent_fd); + + tevent_fd_set_flags(main_fde, flags); +} + + +/* + * tevent_impersonate_add_timer + */ + +static void tevent_impersonate_timer_handler(struct tevent_context *main_ev, + struct tevent_timer *main_te, + struct timeval current_time, + void *private_data); + +static struct tevent_timer *tevent_impersonate_add_timer( + struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + struct timeval next_event, + tevent_timer_handler_t handler, + void *private_data, + const char *handler_name, + const char *location) +{ + struct tevent_impersonate_context *a = + talloc_get_type_abort(ev->additional_data, + struct tevent_impersonate_context); + struct tevent_context *main_ev = a->main_ev; + struct tevent_timer *te; + + te = talloc(mem_ctx?mem_ctx:ev, struct tevent_timer); + if (te == NULL) return NULL; // TODO: fix ugly formatting + + te->event_ctx = ev; + te->next_event = next_event; + te->handler = handler; + te->private_data = private_data; + te->handler_name = handler_name; + te->location = location; + te->additional_data = NULL; + + main_te = _tevent_add_timer(main_ev, te, next_event, + tevent_impersonate_timer_handler, te, + handler_name, location); + if (main_te == NULL) { + talloc_free(te); + return NULL; + } + + te->additional_data = main_te; + + return te; +} + +static void tevent_impersonate_timer_handler(struct tevent_context *main_ev, + struct tevent_timer *main_te, + struct timeval current_time, + void *private_data) +{ + struct tevent_timer *te = + talloc_get_type_abort(private_data, + struct tevent_timer); + struct tevent_context *ev = te->ev; + + tevent_impersonate_become_context(ev); + te->handler(ev, te, current_time, te->private_data); +} + + +/* + * tevent_impersonate_schedule_immediate + */ + +static void tevent_impersonate_immediate_cancel(struct tevent_immediate *im) +{ + if (!im->event_ctx) { + return; + } + + /* let the backend free im->additional_data */ + if (im->cancel_fn) { + im->cancel_fn(im); + } + + im->event_ctx = NULL; + im->handler = NULL; + im->private_data = NULL; + im->handler_name = NULL; + im->schedule_location = NULL; + im->cancel_fn = NULL; + im->additional_data = NULL; + + talloc_set_destructor(im, NULL); +} + +static void tevent_impersonate_schedule_immediate( + struct tevent_immediate *im, + struct tevent_context *ev, + tevent_immediate_handler_t handler, + void *private_data, + const char *handler_name, + const char *location) +{ + struct tevent_impersonate_context *a = + talloc_get_type_abort(ev->additional_data, + struct tevent_impersonate_context); + struct tevent_context *main_ev = a->main_ev; + struct tevent_immediate *main_im; + + main_im = tevent_impersonate_immediate_cancel(im); + + if (handler == NULL) { + return; + } + + if (main_im == NULL) { + main_im = tevent_create_immediate(im); + } + + im->event_ctx = ev; + im->handler = handler; + im->private_data = private_data; + im->handler_name = handler_name; + im->schedule_location = location; + im->cancel_fn = NULL; + im->additional_data = main_im; + + _tevent_schedule_immediate(main_im, main_ev, /* or ev ??? */ + tevent_impersonate_schedule_immediate_handler, + im, handler_name, location); + + // TODO - finish !! -- correct ?? +} + +static void tevent_impersonate_schedule_immediate_handler( + struct tevent_context *main_ev, + struct tevent_immediate *main_im, + void *private_data) +{ + struct tevent_immediate *im = + talloc_get_type_abort(private_data, + struct tevent_immediate); + struct tevent_context *ev = im->ev; + + tevent_impersonate_become_context(ev); + te->handler(ev, se, im->private_data); +} + + +/* + * tevent_impersonate_add_signal + */ +static void tevent_impersonate_signal_handler(struct tevent_context *main_ev, + struct tevent_timer *main_se, + int signum, + int count, + void *siginfo, + void *private_data); + +struct tevent_signal *tevent_impersonate_add_signal(struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + int signum, + int sa_flags, + tevent_signal_handler_t handler, + void *private_data, + const char *handler_name, + const char *location) +{ + struct tevent_impersonate_context *a = + talloc_get_type_abort(ev->additional_data, + struct tevent_impersonate_context); + struct tevent_context *main_ev = a->main_ev; + struct tevent_signal *se; + + se = talloc(mem_ctx?mem_ctx:ev, struct tevent_signal); + if (se == NULL) { + return NULL; + } + + se->event_ctx = ev; + se->signum = signum; + se->sa_flags = sa_flags; + se->handler = handler; + se->private_data = private_data; + se->handler_name = handler_name; + se->location = location; + se->additional_data = NULL; + + main_se = _tevent_add_signal(main_ev, se, signum, sa_flags, + tevent_impersonate_signal_handler, se + handler_name, location); + if (main_se == NULL) { + talloc_free(se); + return NULL; + } + + se->additional_data = main_se; + + return se; +} + +static void tevent_impersonate_signal_handler(struct tevent_context *main_ev, + struct tevent_signal *main_se, + int signum, + int count, + void *siginfo, + void *private_data) +{ + struct tevent_signal *se = + talloc_get_type_abort(private_data, + struct tevent_signal); + struct tevent_context *ev = te->ev; + + tevent_impersonate_become_context(ev); + te->handler(ev, se, signum, count, siginfo, te->private_data); +} + + +/* + * tevent_impersonate_loop_once + */ +static int tevent_impersonate_loop_once(struct tevent_context *ev, + const char *location) +{ + /* + * This should never be called! + * It means we have a nested event loop + */ + smb_panic(location); + errno = ELOOP; + return -1; +} + + +/* + * tevent_impersonate_loop_wait + */ +static int tevent_impersonate_loop_wait(struct tevent_context *ev, + const char *location) +{ + /* + * This should never be called! + * It means we have a nested event loop + */ + smb_panic(location); + errno = ELOOP; + return -1; +} + + +#if 0 +struct tevent_ops { + /* context init */ + int (*context_init)(struct tevent_context *ev); + + /* fd_event functions */ + struct tevent_fd *(*add_fd)(struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + int fd, uint16_t flags, + tevent_fd_handler_t handler, + void *private_data, + const char *handler_name, + const char *location); + void (*set_fd_close_fn)(struct tevent_fd *fde, + tevent_fd_close_fn_t close_fn); + uint16_t (*get_fd_flags)(struct tevent_fd *fde); + void (*set_fd_flags)(struct tevent_fd *fde, uint16_t flags); + + /* timed_event functions */ + struct tevent_timer *(*add_timer)(struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + struct timeval next_event, + tevent_timer_handler_t handler, + void *private_data, + const char *handler_name, + const char *location); + + /* immediate event functions */ + void (*schedule_immediate)(struct tevent_immediate *im, + struct tevent_context *ev, + tevent_immediate_handler_t handler, + void *private_data, + const char *handler_name, + const char *location); + + /* signal functions */ + struct tevent_signal *(*add_signal)(struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + int signum, int sa_flags, + tevent_signal_handler_t handler, + void *private_data, + const char *handler_name, + const char *location); + + /* loop functions */ + int (*loop_once)(struct tevent_context *ev, const char *location); + int (*loop_wait)(struct tevent_context *ev, const char *location); +}; +#endif + +static const struct tevent_ops tevent_impersonate_ops = { + .context_init = tevent_impersonate_init, + .add_fd = tevent_impersonate_add_fd, + .set_fd_close_fn = tevent_impersonate_fd_set_close_fn, + .get_fd_flags = tevent_impersonate_fd_get_flags, + .set_fd_flags = tevent_impersonate_fd_set_flags, + .add_timer = tevent_impersonate_add_timer, + .schedule_immediate = tevent_impersonate_schedule_immediate, + .add_signal = tevent_impersonate_add_signal, + .loop_once = tevent_impersonate_loop_once, + .loop_wait = tevent_impersonate_loop_wait, +}; + +tevent_loop_once + +struct tevent_context *tevent_change_to_user(struct tevent_context *main_ev, + struct connection_struct *conn, + uint64_t vuid) +{ + TALLOC_CTX *mem_ctx = main_ev; // TODO??? + struct tevent_context *ev; + struct tevent_impersonate_context *a; + + a = talloc_zero(mem_ctx, struct tevent_impersonate_context); + if (a == NULL) { + return NULL; + } + a->main_ev = main_ev; + a->conn = conn; + a->vuid = vuid; + + ev = tevent_context_init_ops(mem_ctx, &tevent_impersonate_ops, a); + if (ev == NULL) { + talloc_free(a); + return NULL; + } + + return ev; +} + +struct tevent_context *tevent_change_to_root(struct tevent_context *main_ev) +{ + TALLOC_CTX *mem_ctx = main_ev; // TODO??? + struct tevent_context *ev; + struct tevent_impersonate_context *a; + + a = talloc_zero(mem_ctx, struct tevent_impersonate_context); + if (a == NULL) { + return NULL; + } + a->main_ev = main_ev; + + ev = tevent_context_init_ops(mem_ctx, &tevent_impersonate_ops, a); + if (ev == NULL) { + talloc_free(a); + return NULL; + } + + return ev; +} -- 2.34.1