diff options
Diffstat (limited to 'source3/torture')
-rw-r--r-- | source3/torture/torture.c | 2 | ||||
-rw-r--r-- | source3/torture/wbc_async.c | 774 | ||||
-rw-r--r-- | source3/torture/wbc_async.h | 171 |
3 files changed, 946 insertions, 1 deletions
diff --git a/source3/torture/torture.c b/source3/torture/torture.c index 24c7d7bc35..7821f0eaf4 100644 --- a/source3/torture/torture.c +++ b/source3/torture/torture.c @@ -19,7 +19,7 @@ */ #include "includes.h" -#include "nsswitch/libwbclient/wbc_async.h" +#include "wbc_async.h" #include "torture/proto.h" #include "libcli/security/security.h" #include "tldap.h" diff --git a/source3/torture/wbc_async.c b/source3/torture/wbc_async.c new file mode 100644 index 0000000000..182474c216 --- /dev/null +++ b/source3/torture/wbc_async.c @@ -0,0 +1,774 @@ +/* + Unix SMB/CIFS implementation. + Infrastructure for async winbind requests + Copyright (C) Volker Lendecke 2008 + + ** NOTE! The following LGPL license applies to the wbclient + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include "system/filesys.h" +#include "system/network.h" +#include <talloc.h> +#include <tevent.h> +#include "lib/async_req/async_sock.h" +#include "nsswitch/winbind_struct_protocol.h" +#include "nsswitch/libwbclient/wbclient.h" +#include "wbc_async.h" + +wbcErr map_wbc_err_from_errno(int error) +{ + switch(error) { + case EPERM: + case EACCES: + return WBC_ERR_AUTH_ERROR; + case ENOMEM: + return WBC_ERR_NO_MEMORY; + case EIO: + default: + return WBC_ERR_UNKNOWN_FAILURE; + } +} + +bool tevent_req_is_wbcerr(struct tevent_req *req, wbcErr *pwbc_err) +{ + enum tevent_req_state state; + uint64_t error; + if (!tevent_req_is_error(req, &state, &error)) { + *pwbc_err = WBC_ERR_SUCCESS; + return false; + } + + switch (state) { + case TEVENT_REQ_USER_ERROR: + *pwbc_err = error; + break; + case TEVENT_REQ_TIMED_OUT: + *pwbc_err = WBC_ERR_UNKNOWN_FAILURE; + break; + case TEVENT_REQ_NO_MEMORY: + *pwbc_err = WBC_ERR_NO_MEMORY; + break; + default: + *pwbc_err = WBC_ERR_UNKNOWN_FAILURE; + break; + } + return true; +} + +wbcErr tevent_req_simple_recv_wbcerr(struct tevent_req *req) +{ + wbcErr wbc_err; + + if (tevent_req_is_wbcerr(req, &wbc_err)) { + return wbc_err; + } + + return WBC_ERR_SUCCESS; +} + +struct wbc_debug_ops { + void (*debug)(void *context, enum wbcDebugLevel level, + const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3,0); + void *context; +}; + +struct wb_context { + struct tevent_queue *queue; + int fd; + bool is_priv; + const char *dir; + struct wbc_debug_ops debug_ops; +}; + +static int make_nonstd_fd(int fd) +{ + int i; + int sys_errno = 0; + int fds[3]; + int num_fds = 0; + + if (fd == -1) { + return -1; + } + while (fd < 3) { + fds[num_fds++] = fd; + fd = dup(fd); + if (fd == -1) { + sys_errno = errno; + break; + } + } + for (i=0; i<num_fds; i++) { + close(fds[i]); + } + if (fd == -1) { + errno = sys_errno; + } + return fd; +} + +/**************************************************************************** + Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available, + else + if SYSV use O_NDELAY + if BSD use FNDELAY + Set close on exec also. +****************************************************************************/ + +static int make_safe_fd(int fd) +{ + int result, flags; + int new_fd = make_nonstd_fd(fd); + + if (new_fd == -1) { + goto fail; + } + + /* Socket should be nonblocking. */ + +#ifdef O_NONBLOCK +#define FLAG_TO_SET O_NONBLOCK +#else +#ifdef SYSV +#define FLAG_TO_SET O_NDELAY +#else /* BSD */ +#define FLAG_TO_SET FNDELAY +#endif +#endif + + if ((flags = fcntl(new_fd, F_GETFL)) == -1) { + goto fail; + } + + flags |= FLAG_TO_SET; + if (fcntl(new_fd, F_SETFL, flags) == -1) { + goto fail; + } + +#undef FLAG_TO_SET + + /* Socket should be closed on exec() */ +#ifdef FD_CLOEXEC + result = flags = fcntl(new_fd, F_GETFD, 0); + if (flags >= 0) { + flags |= FD_CLOEXEC; + result = fcntl( new_fd, F_SETFD, flags ); + } + if (result < 0) { + goto fail; + } +#endif + return new_fd; + + fail: + if (new_fd != -1) { + int sys_errno = errno; + close(new_fd); + errno = sys_errno; + } + return -1; +} + +/* Just put a prototype to avoid moving the whole function around */ +static const char *winbindd_socket_dir(void); + +struct wb_context *wb_context_init(TALLOC_CTX *mem_ctx, const char* dir) +{ + struct wb_context *result; + + result = talloc_zero(mem_ctx, struct wb_context); + if (result == NULL) { + return NULL; + } + result->queue = tevent_queue_create(result, "wb_trans"); + if (result->queue == NULL) { + TALLOC_FREE(result); + return NULL; + } + result->fd = -1; + result->is_priv = false; + + if (dir != NULL) { + result->dir = talloc_strdup(result, dir); + } else { + result->dir = winbindd_socket_dir(); + } + if (result->dir == NULL) { + TALLOC_FREE(result); + return NULL; + } + return result; +} + +struct wb_connect_state { + int dummy; +}; + +static void wbc_connect_connected(struct tevent_req *subreq); + +static struct tevent_req *wb_connect_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct wb_context *wb_ctx, + const char *dir) +{ + struct tevent_req *result, *subreq; + struct wb_connect_state *state; + struct sockaddr_un sunaddr; + struct stat st; + char *path = NULL; + wbcErr wbc_err; + + result = tevent_req_create(mem_ctx, &state, struct wb_connect_state); + if (result == NULL) { + return NULL; + } + + if (wb_ctx->fd != -1) { + close(wb_ctx->fd); + wb_ctx->fd = -1; + } + + /* Check permissions on unix socket directory */ + + if (lstat(dir, &st) == -1) { + wbc_err = WBC_ERR_WINBIND_NOT_AVAILABLE; + goto post_status; + } + + if (!S_ISDIR(st.st_mode) || + (st.st_uid != 0 && st.st_uid != geteuid())) { + wbc_err = WBC_ERR_WINBIND_NOT_AVAILABLE; + goto post_status; + } + + /* Connect to socket */ + + path = talloc_asprintf(mem_ctx, "%s/%s", dir, + WINBINDD_SOCKET_NAME); + if (path == NULL) { + goto nomem; + } + + sunaddr.sun_family = AF_UNIX; + strlcpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path)); + TALLOC_FREE(path); + + /* If socket file doesn't exist, don't bother trying to connect + with retry. This is an attempt to make the system usable when + the winbindd daemon is not running. */ + + if ((lstat(sunaddr.sun_path, &st) == -1) + || !S_ISSOCK(st.st_mode) + || (st.st_uid != 0 && st.st_uid != geteuid())) { + wbc_err = WBC_ERR_WINBIND_NOT_AVAILABLE; + goto post_status; + } + + wb_ctx->fd = make_safe_fd(socket(AF_UNIX, SOCK_STREAM, 0)); + if (wb_ctx->fd == -1) { + wbc_err = map_wbc_err_from_errno(errno); + goto post_status; + } + + subreq = async_connect_send(mem_ctx, ev, wb_ctx->fd, + (struct sockaddr *)(void *)&sunaddr, + sizeof(sunaddr)); + if (subreq == NULL) { + goto nomem; + } + tevent_req_set_callback(subreq, wbc_connect_connected, result); + return result; + + post_status: + tevent_req_error(result, wbc_err); + return tevent_req_post(result, ev); + nomem: + TALLOC_FREE(result); + return NULL; +} + +static void wbc_connect_connected(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + int res, err; + + res = async_connect_recv(subreq, &err); + TALLOC_FREE(subreq); + if (res == -1) { + tevent_req_error(req, map_wbc_err_from_errno(err)); + return; + } + tevent_req_done(req); +} + +static wbcErr wb_connect_recv(struct tevent_req *req) +{ + return tevent_req_simple_recv_wbcerr(req); +} + +static const char *winbindd_socket_dir(void) +{ +#ifdef SOCKET_WRAPPER + const char *env_dir; + + env_dir = getenv(WINBINDD_SOCKET_DIR_ENVVAR); + if (env_dir) { + return env_dir; + } +#endif + + return WINBINDD_SOCKET_DIR; +} + +struct wb_open_pipe_state { + struct wb_context *wb_ctx; + struct tevent_context *ev; + bool need_priv; + struct winbindd_request wb_req; +}; + +static void wb_open_pipe_connect_nonpriv_done(struct tevent_req *subreq); +static void wb_open_pipe_ping_done(struct tevent_req *subreq); +static void wb_open_pipe_getpriv_done(struct tevent_req *subreq); +static void wb_open_pipe_connect_priv_done(struct tevent_req *subreq); + +static struct tevent_req *wb_open_pipe_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct wb_context *wb_ctx, + bool need_priv) +{ + struct tevent_req *result, *subreq; + struct wb_open_pipe_state *state; + + result = tevent_req_create(mem_ctx, &state, struct wb_open_pipe_state); + if (result == NULL) { + return NULL; + } + state->wb_ctx = wb_ctx; + state->ev = ev; + state->need_priv = need_priv; + + if (wb_ctx->fd != -1) { + close(wb_ctx->fd); + wb_ctx->fd = -1; + } + + subreq = wb_connect_send(state, ev, wb_ctx, wb_ctx->dir); + if (subreq == NULL) { + goto fail; + } + tevent_req_set_callback(subreq, wb_open_pipe_connect_nonpriv_done, + result); + return result; + + fail: + TALLOC_FREE(result); + return NULL; +} + +static void wb_open_pipe_connect_nonpriv_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct wb_open_pipe_state *state = tevent_req_data( + req, struct wb_open_pipe_state); + wbcErr wbc_err; + + wbc_err = wb_connect_recv(subreq); + TALLOC_FREE(subreq); + if (!WBC_ERROR_IS_OK(wbc_err)) { + state->wb_ctx->is_priv = true; + tevent_req_error(req, wbc_err); + return; + } + + ZERO_STRUCT(state->wb_req); + state->wb_req.cmd = WINBINDD_INTERFACE_VERSION; + state->wb_req.pid = getpid(); + + subreq = wb_simple_trans_send(state, state->ev, NULL, + state->wb_ctx->fd, &state->wb_req); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, wb_open_pipe_ping_done, req); +} + +static void wb_open_pipe_ping_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct wb_open_pipe_state *state = tevent_req_data( + req, struct wb_open_pipe_state); + struct winbindd_response *wb_resp; + int ret, err; + + ret = wb_simple_trans_recv(subreq, state, &wb_resp, &err); + TALLOC_FREE(subreq); + if (ret == -1) { + tevent_req_error(req, map_wbc_err_from_errno(err)); + return; + } + + if (!state->need_priv) { + tevent_req_done(req); + return; + } + + state->wb_req.cmd = WINBINDD_PRIV_PIPE_DIR; + state->wb_req.pid = getpid(); + + subreq = wb_simple_trans_send(state, state->ev, NULL, + state->wb_ctx->fd, &state->wb_req); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, wb_open_pipe_getpriv_done, req); +} + +static void wb_open_pipe_getpriv_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct wb_open_pipe_state *state = tevent_req_data( + req, struct wb_open_pipe_state); + struct winbindd_response *wb_resp = NULL; + int ret, err; + + ret = wb_simple_trans_recv(subreq, state, &wb_resp, &err); + TALLOC_FREE(subreq); + if (ret == -1) { + tevent_req_error(req, map_wbc_err_from_errno(err)); + return; + } + + close(state->wb_ctx->fd); + state->wb_ctx->fd = -1; + + subreq = wb_connect_send(state, state->ev, state->wb_ctx, + (char *)wb_resp->extra_data.data); + TALLOC_FREE(wb_resp); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, wb_open_pipe_connect_priv_done, req); +} + +static void wb_open_pipe_connect_priv_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct wb_open_pipe_state *state = tevent_req_data( + req, struct wb_open_pipe_state); + wbcErr wbc_err; + + wbc_err = wb_connect_recv(subreq); + TALLOC_FREE(subreq); + if (!WBC_ERROR_IS_OK(wbc_err)) { + tevent_req_error(req, wbc_err); + return; + } + state->wb_ctx->is_priv = true; + tevent_req_done(req); +} + +static wbcErr wb_open_pipe_recv(struct tevent_req *req) +{ + return tevent_req_simple_recv_wbcerr(req); +} + +struct wb_trans_state { + struct wb_trans_state *prev, *next; + struct wb_context *wb_ctx; + struct tevent_context *ev; + struct winbindd_request *wb_req; + struct winbindd_response *wb_resp; + bool need_priv; +}; + +static bool closed_fd(int fd) +{ + struct timeval tv; + fd_set r_fds; + int selret; + + if (fd == -1) { + return true; + } + + FD_ZERO(&r_fds); + FD_SET(fd, &r_fds); + ZERO_STRUCT(tv); + + selret = select(fd+1, &r_fds, NULL, NULL, &tv); + if (selret == -1) { + return true; + } + if (selret == 0) { + return false; + } + return (FD_ISSET(fd, &r_fds)); +} + +static void wb_trans_trigger(struct tevent_req *req, void *private_data); +static void wb_trans_connect_done(struct tevent_req *subreq); +static void wb_trans_done(struct tevent_req *subreq); +static void wb_trans_retry_wait_done(struct tevent_req *subreq); + +struct tevent_req *wb_trans_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct wb_context *wb_ctx, bool need_priv, + struct winbindd_request *wb_req) +{ + struct tevent_req *req; + struct wb_trans_state *state; + + req = tevent_req_create(mem_ctx, &state, struct wb_trans_state); + if (req == NULL) { + return NULL; + } + state->wb_ctx = wb_ctx; + state->ev = ev; + state->wb_req = wb_req; + state->need_priv = need_priv; + + if (!tevent_queue_add(wb_ctx->queue, ev, req, wb_trans_trigger, + NULL)) { + tevent_req_nomem(NULL, req); + return tevent_req_post(req, ev); + } + return req; +} + +static void wb_trans_trigger(struct tevent_req *req, void *private_data) +{ + struct wb_trans_state *state = tevent_req_data( + req, struct wb_trans_state); + struct tevent_req *subreq; + + if ((state->wb_ctx->fd != -1) && closed_fd(state->wb_ctx->fd)) { + close(state->wb_ctx->fd); + state->wb_ctx->fd = -1; + } + + if ((state->wb_ctx->fd == -1) + || (state->need_priv && !state->wb_ctx->is_priv)) { + subreq = wb_open_pipe_send(state, state->ev, state->wb_ctx, + state->need_priv); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, wb_trans_connect_done, req); + return; + } + + state->wb_req->pid = getpid(); + + subreq = wb_simple_trans_send(state, state->ev, NULL, + state->wb_ctx->fd, state->wb_req); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, wb_trans_done, req); +} + +static bool wb_trans_retry(struct tevent_req *req, + struct wb_trans_state *state, + wbcErr wbc_err) +{ + struct tevent_req *subreq; + + if (WBC_ERROR_IS_OK(wbc_err)) { + return false; + } + + if (wbc_err == WBC_ERR_WINBIND_NOT_AVAILABLE) { + /* + * Winbind not around or we can't connect to the pipe. Fail + * immediately. + */ + tevent_req_error(req, wbc_err); + return true; + } + + /* + * The transfer as such failed, retry after one second + */ + + if (state->wb_ctx->fd != -1) { + close(state->wb_ctx->fd); + state->wb_ctx->fd = -1; + } + + subreq = tevent_wakeup_send(state, state->ev, + tevent_timeval_current_ofs(1, 0)); + if (tevent_req_nomem(subreq, req)) { + return true; + } + tevent_req_set_callback(subreq, wb_trans_retry_wait_done, req); + return true; +} + +static void wb_trans_retry_wait_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct wb_trans_state *state = tevent_req_data( + req, struct wb_trans_state); + bool ret; + + ret = tevent_wakeup_recv(subreq); + TALLOC_FREE(subreq); + if (!ret) { + tevent_req_error(req, WBC_ERR_UNKNOWN_FAILURE); + return; + } + + subreq = wb_open_pipe_send(state, state->ev, state->wb_ctx, + state->need_priv); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, wb_trans_connect_done, req); +} + +static void wb_trans_connect_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct wb_trans_state *state = tevent_req_data( + req, struct wb_trans_state); + wbcErr wbc_err; + + wbc_err = wb_open_pipe_recv(subreq); + TALLOC_FREE(subreq); + + if (wb_trans_retry(req, state, wbc_err)) { + return; + } + + subreq = wb_simple_trans_send(state, state->ev, NULL, + state->wb_ctx->fd, state->wb_req); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, wb_trans_done, req); +} + +static void wb_trans_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct wb_trans_state *state = tevent_req_data( + req, struct wb_trans_state); + int ret, err; + + ret = wb_simple_trans_recv(subreq, state, &state->wb_resp, &err); + TALLOC_FREE(subreq); + if ((ret == -1) + && wb_trans_retry(req, state, map_wbc_err_from_errno(err))) { + return; + } + + tevent_req_done(req); +} + +wbcErr wb_trans_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, + struct winbindd_response **presponse) +{ + struct wb_trans_state *state = tevent_req_data( + req, struct wb_trans_state); + wbcErr wbc_err; + + if (tevent_req_is_wbcerr(req, &wbc_err)) { + return wbc_err; + } + + *presponse = talloc_move(mem_ctx, &state->wb_resp); + return WBC_ERR_SUCCESS; +} + +/******************************************************************** + * Debug wrapper functions, modeled (with lot's of code copied as is) + * after the tevent debug wrapper functions + ********************************************************************/ + +/* + this allows the user to choose their own debug function +*/ +int wbcSetDebug(struct wb_context *wb_ctx, + void (*debug)(void *context, + enum wbcDebugLevel level, + const char *fmt, + va_list ap) PRINTF_ATTRIBUTE(3,0), + void *context) +{ + wb_ctx->debug_ops.debug = debug; + wb_ctx->debug_ops.context = context; + return 0; +} + +/* + debug function for wbcSetDebugStderr +*/ +static void wbcDebugStderr(void *private_data, + enum wbcDebugLevel level, + const char *fmt, + va_list ap) PRINTF_ATTRIBUTE(3,0); +static void wbcDebugStderr(void *private_data, + enum wbcDebugLevel level, + const char *fmt, va_list ap) +{ + if (level <= WBC_DEBUG_WARNING) { + vfprintf(stderr, fmt, ap); + } +} + +/* + convenience function to setup debug messages on stderr + messages of level WBC_DEBUG_WARNING and higher are printed +*/ +int wbcSetDebugStderr(struct wb_context *wb_ctx) +{ + return wbcSetDebug(wb_ctx, wbcDebugStderr, wb_ctx); +} + +/* + * log a message + * + * The default debug action is to ignore debugging messages. + * This is the most appropriate action for a library. + * Applications using the library must decide where to + * redirect debugging messages +*/ +void wbcDebug(struct wb_context *wb_ctx, enum wbcDebugLevel level, + const char *fmt, ...) +{ + va_list ap; + if (!wb_ctx) { + return; + } + if (wb_ctx->debug_ops.debug == NULL) { + return; + } + va_start(ap, fmt); + wb_ctx->debug_ops.debug(wb_ctx->debug_ops.context, level, fmt, ap); + va_end(ap); +} diff --git a/source3/torture/wbc_async.h b/source3/torture/wbc_async.h new file mode 100644 index 0000000000..6178bb45e9 --- /dev/null +++ b/source3/torture/wbc_async.h @@ -0,0 +1,171 @@ +/* + Unix SMB/CIFS implementation. + Headers for the async winbind client library + Copyright (C) Volker Lendecke 2008 + + ** NOTE! The following LGPL license applies to the wbclient + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _WBC_ASYNC_H_ +#define _WBC_ASYNC_H_ + +#include <talloc.h> +#include <tevent.h> +#include "nsswitch/libwbclient/wbclient.h" +#include "nsswitch/libwbclient/wb_reqtrans.h" + +struct wb_context; +struct winbindd_request; +struct winbindd_response; + +enum wbcDebugLevel { + WBC_DEBUG_FATAL, + WBC_DEBUG_ERROR, + WBC_DEBUG_WARNING, + WBC_DEBUG_TRACE +}; + +struct tevent_req *wb_trans_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct wb_context *wb_ctx, bool need_priv, + struct winbindd_request *wb_req); +wbcErr wb_trans_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, + struct winbindd_response **presponse); +struct wb_context *wb_context_init(TALLOC_CTX *mem_ctx, const char* dir); +int wbcSetDebug(struct wb_context *wb_ctx, + void (*debug)(void *context, + enum wbcDebugLevel level, + const char *fmt, + va_list ap) PRINTF_ATTRIBUTE(3,0), + void *context); +int wbcSetDebugStderr(struct wb_context *wb_ctx); +void wbcDebug(struct wb_context *wb_ctx, enum wbcDebugLevel level, + const char *fmt, ...) PRINTF_ATTRIBUTE(3,0); + +/* Definitions from wb_reqtrans.c */ +wbcErr map_wbc_err_from_errno(int error); + +bool tevent_req_is_wbcerr(struct tevent_req *req, wbcErr *pwbc_err); +wbcErr tevent_req_simple_recv_wbcerr(struct tevent_req *req); + +/* Async functions from wbc_idmap.c */ + +struct tevent_req *wbcSidToUid_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct wb_context *wb_ctx, + const struct wbcDomainSid *sid); +wbcErr wbcSidToUid_recv(struct tevent_req *req, uid_t *puid); + +struct tevent_req *wbcUidToSid_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct wb_context *wb_ctx, + uid_t uid); +wbcErr wbcUidToSid_recv(struct tevent_req *req, struct wbcDomainSid *psid); + +struct tevent_req *wbcSidToGid_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct wb_context *wb_ctx, + const struct wbcDomainSid *sid); +wbcErr wbcSidToGid_recv(struct tevent_req *req, gid_t *pgid); + +struct tevent_req *wbcGidToSid_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct wb_context *wb_ctx, + gid_t gid); +wbcErr wbcGidToSid_recv(struct tevent_req *req, struct wbcDomainSid *psid); + +/* Async functions from wbc_pam.c */ +struct tevent_req *wbcAuthenticateUserEx_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct wb_context *wb_ctx, + const struct wbcAuthUserParams *params); +wbcErr wbcAuthenticateUserEx_recv(struct tevent_req *req, + TALLOC_CTX *mem_ctx, + struct wbcAuthUserInfo **info, + struct wbcAuthErrorInfo **error); + +/* Async functions from wbc_sid.c */ +struct tevent_req *wbcLookupName_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct wb_context *wb_ctx, + const char *domain, + const char *name); +wbcErr wbcLookupName_recv(struct tevent_req *req, + struct wbcDomainSid *sid, + enum wbcSidType *name_type); +struct tevent_req *wbcLookupSid_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct wb_context *wb_ctx, + const struct wbcDomainSid *sid); +wbcErr wbcLookupSid_recv(struct tevent_req *req, + TALLOC_CTX *mem_ctx, + char **pdomain, + char **pname, + enum wbcSidType *pname_type); + +/* Async functions from wbc_util.c */ + +struct tevent_req *wbcPing_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct wb_context *wb_ctx); +wbcErr wbcPing_recv(struct tevent_req *req); + +struct tevent_req *wbcInterfaceVersion_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct wb_context *wb_ctx); +wbcErr wbcInterfaceVersion_recv(struct tevent_req *req, + uint32_t *interface_version); + +struct tevent_req *wbcInfo_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct wb_context *wb_ctx); +wbcErr wbcInfo_recv(struct tevent_req *req, + TALLOC_CTX *mem_ctx, + char *winbind_separator, + char **version_string); + +struct tevent_req *wbcNetbiosName_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct wb_context *wb_ctx); +wbcErr wbcNetbiosName_recv(struct tevent_req *req, + TALLOC_CTX *mem_ctx, + char **netbios_name); + +struct tevent_req *wbcDomainName_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct wb_context *wb_ctx); +wbcErr wbcDomainName_recv(struct tevent_req *req, + TALLOC_CTX *mem_ctx, + char **netbios_name); + +struct tevent_req *wbcInterfaceDetails_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct wb_context *wb_ctx); +wbcErr wbcInterfaceDetails_recv(struct tevent_req *req, + TALLOC_CTX *mem_ctx, + struct wbcInterfaceDetails **details); + +struct tevent_req *wbcDomainInfo_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct wb_context *wb_ctx, + const char *domain); +wbcErr wbcDomainInfo_recv(struct tevent_req *req, + TALLOC_CTX *mem_ctx, + struct wbcDomainInfo **dinfo); + +#endif /*_WBC_ASYNC_H_*/ |