--- /dev/null
+/*
+ Unix SMB/CIFS implementation.
+ async uid/user handling
+ Copyright (C) Stefan Metzmacher 2012
+ Copyright (C) David Disseldorp 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 <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include <tevent.h>
+//#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 const struct tevent_ops s3_event_ops = {
+ .context_init = s3_event_context_init,
+ .add_fd = tevent_common_add_fd,
+ .set_fd_close_fn = tevent_common_fd_set_close_fn,
+ .get_fd_flags = tevent_common_fd_get_flags,
+ .set_fd_flags = tevent_common_fd_set_flags,
+ .add_timer = tevent_common_add_timer,
+ .schedule_immediate = tevent_common_schedule_immediate,
+ .add_signal = tevent_common_add_signal,
+ .loop_once = s3_event_loop_once,
+ .loop_wait = tevent_common_loop_wait,
+};
+
+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;
+}
+
+struct tevent_fd *tevent_common_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_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;
+
+ 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;
+
+ DLIST_ADD(ev->fd_events, fde);
+
+ talloc_set_destructor(fde, tevent_common_fd_destructor);
+
+ return fde;
+}
+
+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_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;
+
+ 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;
+
+ DLIST_ADD(ev->fd_events, fde);
+
+ main_fde = tevent_add_fd(ev, fde, fd, flags,
+ tevent_impersonate_fd_handler, fde);
+ //TODO handler name...
+ 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 = private_data;
+ struct tevent_context *ev = fde->ev;
+ struct tevent_impersonate_context *ctx;
+
+ become_user_user(ctx->conn, ctx->vuid);
+ fde->handler(ev, fde, fde->flags, fde->private_data);
+ //TODO unbecome???
+}
+
+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_once,
+ .loop_wait = tevent_impersonate_loop_wait,
+ //TODO add all!
+};
+
+struct tevent_context *tevent_impersonate_create_context(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;
+}
+