diff options
author | Andrew Tridgell <tridge@samba.org> | 2008-12-16 11:41:20 +1100 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 2008-12-16 11:41:20 +1100 |
commit | f448fde4e35e56508ad93be8de9f60d88e8b8dcd (patch) | |
tree | 597b58ba1af03f5250af918ec15300c385281706 /source3/winbindd | |
parent | a226d86dcec393b2cd657d5441c3041dfdf5cd8f (diff) | |
parent | 530758dc2a6dd6dce083789b328e16e51ba6573d (diff) | |
download | samba-f448fde4e35e56508ad93be8de9f60d88e8b8dcd.tar.gz samba-f448fde4e35e56508ad93be8de9f60d88e8b8dcd.tar.bz2 samba-f448fde4e35e56508ad93be8de9f60d88e8b8dcd.zip |
Merge branch 'master' of ssh://git.samba.org/data/git/samba
Diffstat (limited to 'source3/winbindd')
-rw-r--r-- | source3/winbindd/winbindd.c | 78 | ||||
-rw-r--r-- | source3/winbindd/winbindd_async.c | 24 | ||||
-rw-r--r-- | source3/winbindd/winbindd_cm.c | 2 | ||||
-rw-r--r-- | source3/winbindd/winbindd_group.c | 6 | ||||
-rw-r--r-- | source3/winbindd/winbindd_proto.h | 30 | ||||
-rw-r--r-- | source3/winbindd/winbindd_reqtrans.c | 685 | ||||
-rw-r--r-- | source3/winbindd/winbindd_user.c | 2 |
7 files changed, 771 insertions, 56 deletions
diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index 82af55800f..0ecf11d0e5 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -7,17 +7,17 @@ Copyright (C) Andrew Tridgell 2002 Copyright (C) Jelmer Vernooij 2003 Copyright (C) Volker Lendecke 2004 - + 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/>. */ @@ -103,9 +103,9 @@ static void winbindd_status(void) DEBUG(0, ("winbindd status:\n")); /* Print client state information */ - + DEBUG(0, ("\t%d clients currently active\n", winbindd_num_clients())); - + if (DEBUGLEVEL >= 2 && winbindd_num_clients()) { DEBUG(2, ("\tclient list:\n")); for(tmp = winbindd_client_list(); tmp; tmp = tmp->next) { @@ -157,7 +157,7 @@ static void terminate(bool is_parent) } idmap_close(); - + trustdom_cache_shutdown(); #if 0 @@ -173,35 +173,35 @@ static void terminate(bool is_parent) exit(0); } -static bool do_sigterm; +static SIG_ATOMIC_T do_sigterm = 0; static void termination_handler(int signum) { - do_sigterm = True; + do_sigterm = 1; sys_select_signal(signum); } -static bool do_sigusr2; +static SIG_ATOMIC_T do_sigusr2 = 0; static void sigusr2_handler(int signum) { - do_sigusr2 = True; + do_sigusr2 = 1; sys_select_signal(SIGUSR2); } -static bool do_sighup; +static SIG_ATOMIC_T do_sighup = 0; static void sighup_handler(int signum) { - do_sighup = True; + do_sighup = 1; sys_select_signal(SIGHUP); } -static bool do_sigchld; +static SIG_ATOMIC_T do_sigchld = 0; static void sigchld_handler(int signum) { - do_sigchld = True; + do_sigchld = 1; sys_select_signal(SIGCHLD); } @@ -224,7 +224,7 @@ static void msg_shutdown(struct messaging_context *msg, struct server_id server_id, DATA_BLOB *data) { - do_sigterm = True; + do_sigterm = 1; } @@ -288,7 +288,7 @@ static struct winbindd_dispatch_table { void (*fn)(struct winbindd_cli_state *state); const char *winbindd_cmd_name; } dispatch_table[] = { - + /* User functions */ { WINBINDD_GETPWNAM, winbindd_getpwnam, "GETPWNAM" }, @@ -685,9 +685,9 @@ static void new_connection(int listen_sock, bool privileged) struct winbindd_cli_state *state; socklen_t len; int sock; - + /* Accept connection */ - + len = sizeof(sunaddr); do { @@ -696,16 +696,16 @@ static void new_connection(int listen_sock, bool privileged) if (sock == -1) return; - + DEBUG(6,("accepted socket %d\n", sock)); - + /* Create new connection structure */ - + if ((state = TALLOC_ZERO_P(NULL, struct winbindd_cli_state)) == NULL) { close(sock); return; } - + state->sock = sock; state->last_access = time(NULL); @@ -720,7 +720,7 @@ static void new_connection(int listen_sock, bool privileged) request_len_recv, state); /* Add to connection list */ - + winbindd_add_client(state); } @@ -731,7 +731,7 @@ static void remove_client(struct winbindd_cli_state *state) char c = 0; /* It's a dead client - hold a funeral */ - + if (state == NULL) { return; } @@ -740,14 +740,14 @@ static void remove_client(struct winbindd_cli_state *state) write(state->sock, &c, sizeof(c)); /* Close socket */ - + close(state->sock); - + /* Free any getent state */ - + free_getent_state(state->getpwent_state); free_getent_state(state->getgrent_state); - + /* We may have some extra data that was not freed if the client was killed unexpectedly */ @@ -756,9 +756,9 @@ static void remove_client(struct winbindd_cli_state *state) TALLOC_FREE(state->mem_ctx); remove_fd_event(&state->fd_event); - + /* Remove from list and free */ - + winbindd_remove_client(state); TALLOC_FREE(state); } @@ -802,7 +802,7 @@ void winbind_check_sighup(const char *lfile) flush_caches(); reload_services_file(lfile); - do_sighup = False; + do_sighup = 0; } } @@ -893,7 +893,7 @@ static void process_loop(void) } /* Call select */ - + selret = sys_select(maxfd + 1, &r_fds, &w_fds, NULL, &timeout); if (selret == 0) { @@ -944,7 +944,7 @@ static void process_loop(void) /* new, non-privileged connection */ new_connection(listen_sock, False); } - + if (FD_ISSET(listen_priv_sock, &r_fds)) { while (winbindd_num_clients() > WINBINDD_MAX_SIMULTANEOUS_CLIENTS - 1) { @@ -977,13 +977,13 @@ static void process_loop(void) if (do_sigusr2) { print_winbindd_status(); - do_sigusr2 = False; + do_sigusr2 = 0; } if (do_sigchld) { pid_t pid; - do_sigchld = False; + do_sigchld = 0; while ((pid = sys_waitpid(-1, NULL, WNOHANG)) > 0) { winbind_child_died(pid); @@ -1159,7 +1159,7 @@ int main(int argc, char **argv, char **envp) BlockSignals(False, SIGCHLD); /* Setup signal handlers */ - + CatchSignal(SIGINT, termination_handler); /* Exit on these sigs */ CatchSignal(SIGQUIT, termination_handler); CatchSignal(SIGTERM, termination_handler); @@ -1232,13 +1232,13 @@ int main(int argc, char **argv, char **envp) messaging_register(winbind_messaging_context(), NULL, MSG_DEBUG, winbind_msg_debug); - + netsamlogon_cache_init(); /* Non-critical */ - + /* clear the cached list of trusted domains */ wcache_tdc_clear(); - + if (!init_domain_list()) { DEBUG(0,("unable to initialize domain list\n")); exit(1); diff --git a/source3/winbindd/winbindd_async.c b/source3/winbindd/winbindd_async.c index 7500bcbe5b..7b93f963b4 100644 --- a/source3/winbindd/winbindd_async.c +++ b/source3/winbindd/winbindd_async.c @@ -5,7 +5,7 @@ Copyright (C) Volker Lendecke 2005 Copyright (C) Gerald Carter 2006 - + The helpers always consist of three functions: * A request setup function that takes the necessary parameters together @@ -21,12 +21,12 @@ 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/>. */ @@ -166,7 +166,7 @@ static void lookupsid_recv(TALLOC_CTX *mem_ctx, bool success, /* Try again using the forest root */ struct winbindd_domain *root_domain = find_root_domain(); struct winbindd_request request; - + if ( !root_domain ) { DEBUG(5,("lookupsid_recv: unable to determine forest root\n")); cont(s->caller_private_data, False, NULL, NULL, SID_NAME_UNKNOWN); @@ -491,7 +491,7 @@ void winbindd_listent_async(TALLOC_CTX *mem_ctx, do_async_domain(mem_ctx, domain, &request, listent_recv, (void *)cont, private_data); } - + enum winbindd_result winbindd_dual_list_users(struct winbindd_domain *domain, struct winbindd_cli_state *state) { @@ -509,7 +509,7 @@ enum winbindd_result winbindd_dual_list_users(struct winbindd_domain *domain, methods = domain->methods; status = methods->query_user_list(domain, state->mem_ctx, &num_entries, &info); - + if (!NT_STATUS_IS_OK(status)) return WINBINDD_ERROR; @@ -521,7 +521,7 @@ enum winbindd_result winbindd_dual_list_users(struct winbindd_domain *domain, +1 for the ',' between group names */ extra_data = (char *)SMB_REALLOC(extra_data, (sizeof(fstring) + 1) * num_entries); - + if (!extra_data) { DEBUG(0,("failed to enlarge buffer!\n")); return WINBINDD_ERROR; @@ -530,12 +530,12 @@ enum winbindd_result winbindd_dual_list_users(struct winbindd_domain *domain, /* Pack user list into extra data fields */ for (i = 0; i < num_entries; i++) { fstring acct_name, name; - + if (info[i].acct_name == NULL) fstrcpy(acct_name, ""); else fstrcpy(acct_name, info[i].acct_name); - + fill_domain_username(name, domain->name, acct_name, True); /* Append to extra data */ memcpy(&extra_data[extra_data_len], name, strlen(name)); @@ -904,7 +904,7 @@ enum winbindd_result winbindd_dual_getsidaliases(struct winbindd_domain *domain, (char *)state->response.extra_data.data)); state->response.length += len+1; } - + return WINBINDD_OK; } @@ -926,7 +926,7 @@ static void gettoken_recvdomgroups(TALLOC_CTX *mem_ctx, bool success, static void gettoken_recvaliases(void *private_data, bool success, const DOM_SID *aliases, size_t num_aliases); - + void winbindd_gettoken_async(TALLOC_CTX *mem_ctx, const DOM_SID *user_sid, void (*cont)(void *private_data, bool success, @@ -975,7 +975,7 @@ static void gettoken_recvdomgroups(TALLOC_CTX *mem_ctx, bool success, struct gettoken_state *state = talloc_get_type_abort(private_data, struct gettoken_state); char *sids_str; - + if (!success) { DEBUG(10, ("Could not get domain groups\n")); state->cont(state->private_data, False, NULL, 0); diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 3c69859731..5f592fc6b7 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -1038,7 +1038,7 @@ static bool add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name, /* Make sure there's no duplicates in the list */ for (i=0; i<*num; i++) - if (addr_equal((struct sockaddr *)&(*dcs)[i].ss, (struct sockaddr *)pss)) + if (sockaddr_equal((struct sockaddr *)&(*dcs)[i].ss, (struct sockaddr *)pss)) return False; *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1); diff --git a/source3/winbindd/winbindd_group.c b/source3/winbindd/winbindd_group.c index 3422fdba1c..7432bda451 100644 --- a/source3/winbindd/winbindd_group.c +++ b/source3/winbindd/winbindd_group.c @@ -800,7 +800,7 @@ void winbindd_getgrnam(struct winbindd_cli_state *state) /* Get info for the domain */ - if ((domain = find_domain_from_name(name_domain)) == NULL) { + if ((domain = find_domain_from_name_noinit(name_domain)) == NULL) { DEBUG(3, ("could not get domain sid for domain %s\n", name_domain)); request_error(state); @@ -833,7 +833,7 @@ struct getgrsid_state { }; static void getgrsid_sid2gid_recv(void *private_data, bool success, gid_t gid) - { +{ struct getgrsid_state *s = (struct getgrsid_state *)private_data; struct winbindd_domain *domain; @@ -884,7 +884,7 @@ static void getgrsid_sid2gid_recv(void *private_data, bool success, gid_t gid) s->state->response.extra_data.data = gr_mem; request_ok(s->state); - } +} static void getgrsid_lookupsid_recv( void *private_data, bool success, const char *dom_name, const char *name, diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index 9de385e3b3..92ce1f9850 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -67,6 +67,36 @@ void winbind_check_sighup(const char *lfile); void winbind_check_sigterm(bool in_parent); int main(int argc, char **argv, char **envp); +/* The following definitions come from winbindd/winbindd_reqtrans.c */ + +struct async_req *wb_req_read_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + int fd, size_t max_extra_data); +NTSTATUS wb_req_read_recv(struct async_req *req, TALLOC_CTX *mem_ctx, + struct winbindd_request **preq); +struct async_req *wb_req_write_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, int fd, + struct winbindd_request *wb_req); +NTSTATUS wb_req_write_recv(struct async_req *req); + +struct async_req *wb_resp_read_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, int fd); +NTSTATUS wb_resp_read_recv(struct async_req *req, TALLOC_CTX *mem_ctx, + struct winbindd_response **presp); +struct async_req *wb_resp_write_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, int fd, + struct winbindd_response *wb_resp); +NTSTATUS wb_resp_write_recv(struct async_req *req); + +struct async_req *wb_trans_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + int fd, + struct winbindd_request *wb_req, + struct timeval timeout, + size_t reply_max_extra_data); +NTSTATUS wb_trans_recv(struct async_req *req, TALLOC_CTX *mem_ctx, + struct winbindd_response **presp); + /* The following definitions come from winbindd/winbindd_ads.c */ diff --git a/source3/winbindd/winbindd_reqtrans.c b/source3/winbindd/winbindd_reqtrans.c new file mode 100644 index 0000000000..ea16c5f81e --- /dev/null +++ b/source3/winbindd/winbindd_reqtrans.c @@ -0,0 +1,685 @@ +/* + Unix SMB/CIFS implementation. + + Async transfer of winbindd_request and _response structs + + Copyright (C) Volker Lendecke 2008 + + 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 "winbindd.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_WINBIND + +struct req_read_state { + struct winbindd_request *wb_req; + struct event_context *ev; + size_t max_extra_data; + int fd; +}; + +static void wb_req_read_len(struct async_req *subreq); +static void wb_req_read_main(struct async_req *subreq); +static void wb_req_read_extra(struct async_req *subreq); + +struct async_req *wb_req_read_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + int fd, size_t max_extra_data) +{ + struct async_req *result, *subreq; + struct req_read_state *state; + + result = async_req_new(mem_ctx, ev); + if (result == NULL) { + return NULL; + } + + state = talloc(result, struct req_read_state); + if (state == NULL) { + goto nomem; + } + result->private_data = state; + + state->fd = fd; + state->ev = ev; + state->max_extra_data = max_extra_data; + state->wb_req = talloc(state, struct winbindd_request); + if (state->wb_req == NULL) { + goto nomem; + } + + subreq = recvall_send(state, ev, state->fd, &(state->wb_req->length), + sizeof(state->wb_req->length), 0); + if (subreq == NULL) { + goto nomem; + } + + subreq->async.fn = wb_req_read_len; + subreq->async.priv = result; + return result; + + nomem: + TALLOC_FREE(result); + return NULL; +} + +static void wb_req_read_len(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct req_read_state *state = talloc_get_type_abort( + req->private_data, struct req_read_state); + NTSTATUS status; + + status = recvall_recv(subreq); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_error(req, status); + return; + } + + if (state->wb_req->length != sizeof(struct winbindd_request)) { + DEBUG(0, ("wb_req_read_len: Invalid request size received: " + "%d (expected %d)\n", (int)state->wb_req->length, + (int)sizeof(struct winbindd_request))); + async_req_error(req, NT_STATUS_INVALID_BUFFER_SIZE); + return; + } + + subreq = recvall_send( + req, state->ev, state->fd, (uint32 *)(state->wb_req)+1, + sizeof(struct winbindd_request) - sizeof(uint32), 0); + if (async_req_nomem(subreq, req)) { + return; + } + + subreq->async.fn = wb_req_read_main; + subreq->async.priv = req; +} + +static void wb_req_read_main(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct req_read_state *state = talloc_get_type_abort( + req->private_data, struct req_read_state); + NTSTATUS status; + + status = recvall_recv(subreq); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_error(req, status); + return; + } + + if ((state->max_extra_data != 0) + && (state->wb_req->extra_len > state->max_extra_data)) { + DEBUG(3, ("Got request with %d bytes extra data on " + "unprivileged socket\n", + (int)state->wb_req->extra_len)); + async_req_error(req, NT_STATUS_INVALID_BUFFER_SIZE); + return; + } + + if (state->wb_req->extra_len == 0) { + async_req_done(req); + return; + } + + state->wb_req->extra_data.data = TALLOC_ARRAY( + state->wb_req, char, state->wb_req->extra_len + 1); + if (async_req_nomem(state->wb_req->extra_data.data, req)) { + return; + } + + state->wb_req->extra_data.data[state->wb_req->extra_len] = 0; + + subreq = recvall_send( + req, state->ev, state->fd, state->wb_req->extra_data.data, + state->wb_req->extra_len, 0); + if (async_req_nomem(subreq, req)) { + return; + } + + subreq->async.fn = wb_req_read_extra; + subreq->async.priv = req; +} + +static void wb_req_read_extra(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + NTSTATUS status; + + status = recvall_recv(subreq); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_error(req, status); + return; + } + async_req_done(req); +} + + +NTSTATUS wb_req_read_recv(struct async_req *req, TALLOC_CTX *mem_ctx, + struct winbindd_request **preq) +{ + struct req_read_state *state = talloc_get_type_abort( + req->private_data, struct req_read_state); + NTSTATUS status; + + if (async_req_is_error(req, &status)) { + return status; + } + *preq = talloc_move(mem_ctx, &state->wb_req); + return NT_STATUS_OK; +} + +struct req_write_state { + struct winbindd_request *wb_req; + struct event_context *ev; + int fd; +}; + +static void wb_req_write_main(struct async_req *subreq); +static void wb_req_write_extra(struct async_req *subreq); + +struct async_req *wb_req_write_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, int fd, + struct winbindd_request *wb_req) +{ + struct async_req *result, *subreq; + struct req_write_state *state; + + result = async_req_new(mem_ctx, ev); + if (result == NULL) { + return NULL; + } + + state = talloc(result, struct req_write_state); + if (state == NULL) { + goto nomem; + } + result->private_data = state; + + state->fd = fd; + state->ev = ev; + state->wb_req = wb_req; + + subreq = sendall_send(state, state->ev, state->fd, state->wb_req, + sizeof(struct winbindd_request), 0); + if (subreq == NULL) { + goto nomem; + } + + subreq->async.fn = wb_req_write_main; + subreq->async.priv = result; + return result; + + nomem: + TALLOC_FREE(result); + return NULL; +} + +static void wb_req_write_main(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct req_write_state *state = talloc_get_type_abort( + req->private_data, struct req_write_state); + NTSTATUS status; + + status = sendall_recv(subreq); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_error(req, status); + return; + } + + if (state->wb_req->extra_len == 0) { + async_req_done(req); + return; + } + + subreq = sendall_send(state, state->ev, state->fd, + state->wb_req->extra_data.data, + state->wb_req->extra_len, 0); + if (async_req_nomem(subreq, req)) { + return; + } + + subreq->async.fn = wb_req_write_extra; + subreq->async.priv = req; +} + +static void wb_req_write_extra(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + NTSTATUS status; + + status = sendall_recv(subreq); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_error(req, status); + return; + } + + async_req_done(req); +} + +NTSTATUS wb_req_write_recv(struct async_req *req) +{ + return async_req_simple_recv(req); +} + +struct resp_read_state { + struct winbindd_response *wb_resp; + struct event_context *ev; + size_t max_extra_data; + int fd; +}; + +static void wb_resp_read_len(struct async_req *subreq); +static void wb_resp_read_main(struct async_req *subreq); +static void wb_resp_read_extra(struct async_req *subreq); + +struct async_req *wb_resp_read_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, int fd) +{ + struct async_req *result, *subreq; + struct resp_read_state *state; + + result = async_req_new(mem_ctx, ev); + if (result == NULL) { + return NULL; + } + + state = talloc(result, struct resp_read_state); + if (state == NULL) { + goto nomem; + } + result->private_data = state; + + state->fd = fd; + state->ev = ev; + state->wb_resp = talloc(state, struct winbindd_response); + if (state->wb_resp == NULL) { + goto nomem; + } + + subreq = recvall_send(state, ev, state->fd, &(state->wb_resp->length), + sizeof(state->wb_resp->length), 0); + if (subreq == NULL) { + goto nomem; + } + + subreq->async.fn = wb_resp_read_len; + subreq->async.priv = result; + return result; + + nomem: + TALLOC_FREE(result); + return NULL; +} + +static void wb_resp_read_len(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct resp_read_state *state = talloc_get_type_abort( + req->private_data, struct resp_read_state); + NTSTATUS status; + + status = recvall_recv(subreq); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_error(req, status); + return; + } + + if (state->wb_resp->length < sizeof(struct winbindd_response)) { + DEBUG(0, ("wb_resp_read_len: Invalid response size received: " + "%d (expected at least%d)\n", + (int)state->wb_resp->length, + (int)sizeof(struct winbindd_response))); + async_req_error(req, NT_STATUS_INVALID_BUFFER_SIZE); + return; + } + + subreq = recvall_send( + req, state->ev, state->fd, (uint32 *)(state->wb_resp)+1, + sizeof(struct winbindd_response) - sizeof(uint32), 0); + if (async_req_nomem(subreq, req)) { + return; + } + + subreq->async.fn = wb_resp_read_main; + subreq->async.priv = req; +} + +static void wb_resp_read_main(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct resp_read_state *state = talloc_get_type_abort( + req->private_data, struct resp_read_state); + NTSTATUS status; + size_t extra_len; + + status = recvall_recv(subreq); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_error(req, status); + return; + } + + extra_len = state->wb_resp->length - sizeof(struct winbindd_response); + if (extra_len == 0) { + async_req_done(req); + return; + } + + state->wb_resp->extra_data.data = TALLOC_ARRAY( + state->wb_resp, char, extra_len+1); + if (async_req_nomem(state->wb_resp->extra_data.data, req)) { + return; + } + ((char *)state->wb_resp->extra_data.data)[extra_len] = 0; + + subreq = recvall_send( + req, state->ev, state->fd, state->wb_resp->extra_data.data, + extra_len, 0); + if (async_req_nomem(subreq, req)) { + return; + } + + subreq->async.fn = wb_resp_read_extra; + subreq->async.priv = req; +} + +static void wb_resp_read_extra(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + NTSTATUS status; + + status = recvall_recv(subreq); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_error(req, status); + return; + } + async_req_done(req); +} + + +NTSTATUS wb_resp_read_recv(struct async_req *req, TALLOC_CTX *mem_ctx, + struct winbindd_response **presp) +{ + struct resp_read_state *state = talloc_get_type_abort( + req->private_data, struct resp_read_state); + NTSTATUS status; + + if (async_req_is_error(req, &status)) { + return status; + } + *presp = talloc_move(mem_ctx, &state->wb_resp); + return NT_STATUS_OK; +} + +struct resp_write_state { + struct winbindd_response *wb_resp; + struct event_context *ev; + int fd; +}; + +static void wb_resp_write_main(struct async_req *subreq); +static void wb_resp_write_extra(struct async_req *subreq); + +struct async_req *wb_resp_write_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, int fd, + struct winbindd_response *wb_resp) +{ + struct async_req *result, *subreq; + struct resp_write_state *state; + + result = async_req_new(mem_ctx, ev); + if (result == NULL) { + return NULL; + } + + state = talloc(result, struct resp_write_state); + if (state == NULL) { + goto nomem; + } + result->private_data = state; + + state->fd = fd; + state->ev = ev; + state->wb_resp = wb_resp; + + subreq = sendall_send(state, state->ev, state->fd, state->wb_resp, + sizeof(struct winbindd_response), 0); + if (subreq == NULL) { + goto nomem; + } + + subreq->async.fn = wb_resp_write_main; + subreq->async.priv = result; + return result; + + nomem: + TALLOC_FREE(result); + return NULL; +} + +static void wb_resp_write_main(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct resp_write_state *state = talloc_get_type_abort( + req->private_data, struct resp_write_state); + NTSTATUS status; + + status = sendall_recv(subreq); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_error(req, status); + return; + } + + if (state->wb_resp->length == sizeof(struct winbindd_response)) { + async_req_done(req); + return; + } + + subreq = sendall_send( + state, state->ev, state->fd, + state->wb_resp->extra_data.data, + state->wb_resp->length - sizeof(struct winbindd_response), 0); + if (async_req_nomem(subreq, req)) { + return; + } + + subreq->async.fn = wb_resp_write_extra; + subreq->async.priv = req; +} + +static void wb_resp_write_extra(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + NTSTATUS status; + + status = sendall_recv(subreq); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_error(req, status); + return; + } + + async_req_done(req); +} + +NTSTATUS wb_resp_write_recv(struct async_req *req) +{ + return async_req_simple_recv(req); +} + +struct wb_trans_state { + struct event_context *ev; + struct timed_event *te; + int fd; + struct winbindd_response *wb_resp; + size_t reply_max_extra_data; +}; + +static void wb_trans_timeout(struct event_context *ev, struct timed_event *te, + const struct timeval *now, void *priv); +static void wb_trans_sent(struct async_req *req); +static void wb_trans_received(struct async_req *req); + +struct async_req *wb_trans_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + int fd, + struct winbindd_request *wb_req, + struct timeval timeout, + size_t reply_max_extra_data) +{ + struct async_req *result, *subreq; + struct wb_trans_state *state; + + result = async_req_new(mem_ctx, ev); + if (result == NULL) { + return NULL; + } + + state = talloc(result, struct wb_trans_state); + if (state == NULL) { + goto nomem; + } + result->private_data = state; + + state->ev = ev; + state->fd = fd; + state->reply_max_extra_data = reply_max_extra_data; + + state->te = event_add_timed( + ev, state, + timeval_current_ofs(timeout.tv_sec, timeout.tv_usec), + "wb_trans_timeout", wb_trans_timeout, result); + if (state->te == NULL) { + goto nomem; + } + + subreq = wb_req_write_send(state, state->ev, state->fd, wb_req); + if (subreq == NULL) { + goto nomem; + } + subreq->async.fn = wb_trans_sent; + subreq->async.priv = result; + + return result; + + nomem: + TALLOC_FREE(result); + return NULL; +} + +static void wb_trans_timeout(struct event_context *ev, struct timed_event *te, + const struct timeval *now, void *priv) +{ + struct async_req *req = talloc_get_type_abort( + priv, struct async_req); + struct wb_trans_state *state = talloc_get_type_abort( + req->private_data, struct wb_trans_state); + + TALLOC_FREE(state->te); + async_req_error(req, NT_STATUS_IO_TIMEOUT); +} + +static void wb_trans_sent(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct wb_trans_state *state = talloc_get_type_abort( + req->private_data, struct wb_trans_state); + NTSTATUS status; + + status = wb_req_write_recv(subreq); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_error(req, status); + return; + } + + subreq = wb_resp_read_send(state, state->ev, state->fd); + if (async_req_nomem(subreq, req)) { + return; + } + + subreq->async.fn = wb_trans_received; + subreq->async.priv = req; +}; + +static void wb_trans_received(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct wb_trans_state *state = talloc_get_type_abort( + req->private_data, struct wb_trans_state); + NTSTATUS status; + + TALLOC_FREE(state->te); + + status = wb_resp_read_recv(subreq, state, &state->wb_resp); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + async_req_error(req, status); + return; + } + + async_req_done(req); +} + +NTSTATUS wb_trans_recv(struct async_req *req, TALLOC_CTX *mem_ctx, + struct winbindd_response **presp) +{ + struct wb_trans_state *state = talloc_get_type_abort( + req->private_data, struct wb_trans_state); + NTSTATUS status; + + if (async_req_is_error(req, &status)) { + return status; + } + *presp = talloc_move(mem_ctx, &state->wb_resp); + return NT_STATUS_OK; +} + +struct wb_trans_queue_state { + struct wb_trans_queue_state *prev, *next; + struct wb_trans_queue *queue; + struct winbindd_request *req; +}; + +struct wb_trans_queue { + int fd; + struct timeval timeout; + size_t max_resp_extra_data; + struct wb_trans_queue_state *queued_requests; +}; diff --git a/source3/winbindd/winbindd_user.c b/source3/winbindd/winbindd_user.c index e5d0a22a73..fd1fdd3699 100644 --- a/source3/winbindd/winbindd_user.c +++ b/source3/winbindd/winbindd_user.c @@ -456,7 +456,7 @@ void winbindd_getpwnam(struct winbindd_cli_state *state) /* Get info for the domain */ - domain = find_domain_from_name(domname); + domain = find_domain_from_name_noinit(domname); if (domain == NULL) { DEBUG(7, ("could not find domain entry for domain %s. " |