diff options
Diffstat (limited to 'source3')
-rw-r--r-- | source3/Makefile.in | 4 | ||||
-rw-r--r-- | source3/lib/wb_reqtrans.c | 446 | ||||
-rw-r--r-- | source3/lib/wb_reqtrans.h | 61 | ||||
-rw-r--r-- | source3/torture/wbc_async.h | 2 | ||||
-rw-r--r-- | source3/winbindd/winbindd.c | 2 | ||||
-rw-r--r-- | source3/winbindd/winbindd_dual.c | 2 | ||||
-rw-r--r-- | source3/wscript_build | 4 |
7 files changed, 514 insertions, 7 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in index 1104216550..8a150f2064 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -1204,7 +1204,7 @@ SMBTORTURE_OBJ = $(SMBTORTURE_OBJ1) $(PARAM_OBJ) $(TLDAP_OBJ) \ $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) $(LIB_NONSMBD_OBJ) \ @LIBWBCLIENT_STATIC@ \ torture/wbc_async.o \ - ../nsswitch/libwbclient/wb_reqtrans.o \ + lib/wb_reqtrans.o \ $(LIBMSRPC_OBJ) $(LIBMSRPC_GEN_OBJ) $(LIBCLI_ECHO_OBJ) MASKTEST_OBJ = torture/masktest.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) \ @@ -1400,7 +1400,7 @@ WINBINDD_OBJ1 = \ auth/server_info_sam.o \ auth/user_info.o \ auth/pampass.o \ - ../nsswitch/libwbclient/wb_reqtrans.o + lib/wb_reqtrans.o WINBINDD_OBJ = \ $(WINBINDD_OBJ1) $(PASSDB_OBJ) $(GROUPDB_OBJ) \ diff --git a/source3/lib/wb_reqtrans.c b/source3/lib/wb_reqtrans.c new file mode 100644 index 0000000000..78f806dc0d --- /dev/null +++ b/source3/lib/wb_reqtrans.c @@ -0,0 +1,446 @@ +/* + Unix SMB/CIFS implementation. + + Async transfer of winbindd_request and _response structs + + 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 "lib/util/tevent_unix.h" +#include "nsswitch/winbind_struct_protocol.h" +#include "nsswitch/libwbclient/wbclient.h" +#include "lib/wb_reqtrans.h" + +/* can't use DEBUG here... */ +#define DEBUG(a,b) + +struct req_read_state { + struct winbindd_request *wb_req; + size_t max_extra_data; + ssize_t ret; +}; + +static ssize_t wb_req_more(uint8_t *buf, size_t buflen, void *private_data); +static void wb_req_read_done(struct tevent_req *subreq); + +struct tevent_req *wb_req_read_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + int fd, size_t max_extra_data) +{ + struct tevent_req *req, *subreq; + struct req_read_state *state; + + req = tevent_req_create(mem_ctx, &state, struct req_read_state); + if (req == NULL) { + return NULL; + } + state->max_extra_data = max_extra_data; + + subreq = read_packet_send(state, ev, fd, 4, wb_req_more, state); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, wb_req_read_done, req); + return req; +} + +static ssize_t wb_req_more(uint8_t *buf, size_t buflen, void *private_data) +{ + struct req_read_state *state = talloc_get_type_abort( + private_data, struct req_read_state); + struct winbindd_request *req = (struct winbindd_request *)buf; + + if (buflen == 4) { + if (req->length != sizeof(struct winbindd_request)) { + DEBUG(0, ("wb_req_read_len: Invalid request size " + "received: %d (expected %d)\n", + (int)req->length, + (int)sizeof(struct winbindd_request))); + return -1; + } + return sizeof(struct winbindd_request) - 4; + } + + if (buflen > sizeof(struct winbindd_request)) { + /* We've been here, we're done */ + return 0; + } + + if ((state->max_extra_data != 0) + && (req->extra_len > state->max_extra_data)) { + DEBUG(3, ("Got request with %d bytes extra data on " + "unprivileged socket\n", (int)req->extra_len)); + return -1; + } + + return req->extra_len; +} + +static void wb_req_read_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct req_read_state *state = tevent_req_data( + req, struct req_read_state); + int err; + uint8_t *buf; + + state->ret = read_packet_recv(subreq, state, &buf, &err); + TALLOC_FREE(subreq); + if (state->ret == -1) { + tevent_req_error(req, err); + return; + } + + state->wb_req = (struct winbindd_request *)buf; + + if (state->wb_req->extra_len != 0) { + state->wb_req->extra_data.data = + (char *)buf + sizeof(struct winbindd_request); + } else { + state->wb_req->extra_data.data = NULL; + } + tevent_req_done(req); +} + +ssize_t wb_req_read_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, + struct winbindd_request **preq, int *err) +{ + struct req_read_state *state = tevent_req_data( + req, struct req_read_state); + + if (tevent_req_is_unix_error(req, err)) { + return -1; + } + *preq = talloc_move(mem_ctx, &state->wb_req); + return state->ret; +} + +struct req_write_state { + struct iovec iov[2]; + ssize_t ret; +}; + +static void wb_req_write_done(struct tevent_req *subreq); + +struct tevent_req *wb_req_write_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct tevent_queue *queue, int fd, + struct winbindd_request *wb_req) +{ + struct tevent_req *req, *subreq; + struct req_write_state *state; + int count = 1; + + req = tevent_req_create(mem_ctx, &state, struct req_write_state); + if (req == NULL) { + return NULL; + } + + state->iov[0].iov_base = (void *)wb_req; + state->iov[0].iov_len = sizeof(struct winbindd_request); + + if (wb_req->extra_len != 0) { + state->iov[1].iov_base = (void *)wb_req->extra_data.data; + state->iov[1].iov_len = wb_req->extra_len; + count = 2; + } + + subreq = writev_send(state, ev, queue, fd, true, state->iov, count); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, wb_req_write_done, req); + return req; +} + +static void wb_req_write_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct req_write_state *state = tevent_req_data( + req, struct req_write_state); + int err; + + state->ret = writev_recv(subreq, &err); + TALLOC_FREE(subreq); + if (state->ret < 0) { + tevent_req_error(req, err); + return; + } + tevent_req_done(req); +} + +ssize_t wb_req_write_recv(struct tevent_req *req, int *err) +{ + struct req_write_state *state = tevent_req_data( + req, struct req_write_state); + + if (tevent_req_is_unix_error(req, err)) { + return -1; + } + return state->ret; +} + +struct resp_read_state { + struct winbindd_response *wb_resp; + ssize_t ret; +}; + +static ssize_t wb_resp_more(uint8_t *buf, size_t buflen, void *private_data); +static void wb_resp_read_done(struct tevent_req *subreq); + +struct tevent_req *wb_resp_read_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, int fd) +{ + struct tevent_req *req, *subreq; + struct resp_read_state *state; + + req = tevent_req_create(mem_ctx, &state, struct resp_read_state); + if (req == NULL) { + return NULL; + } + + subreq = read_packet_send(state, ev, fd, 4, wb_resp_more, state); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, wb_resp_read_done, req); + return req; +} + +static ssize_t wb_resp_more(uint8_t *buf, size_t buflen, void *private_data) +{ + struct winbindd_response *resp = (struct winbindd_response *)buf; + + if (buflen == 4) { + if (resp->length < sizeof(struct winbindd_response)) { + DEBUG(0, ("wb_resp_read_len: Invalid response size " + "received: %d (expected at least%d)\n", + (int)resp->length, + (int)sizeof(struct winbindd_response))); + return -1; + } + } + return resp->length - buflen; +} + +static void wb_resp_read_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct resp_read_state *state = tevent_req_data( + req, struct resp_read_state); + uint8_t *buf; + int err; + + state->ret = read_packet_recv(subreq, state, &buf, &err); + TALLOC_FREE(subreq); + if (state->ret == -1) { + tevent_req_error(req, err); + return; + } + + state->wb_resp = (struct winbindd_response *)buf; + + if (state->wb_resp->length > sizeof(struct winbindd_response)) { + state->wb_resp->extra_data.data = + (char *)buf + sizeof(struct winbindd_response); + } else { + state->wb_resp->extra_data.data = NULL; + } + tevent_req_done(req); +} + +ssize_t wb_resp_read_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, + struct winbindd_response **presp, int *err) +{ + struct resp_read_state *state = tevent_req_data( + req, struct resp_read_state); + + if (tevent_req_is_unix_error(req, err)) { + return -1; + } + *presp = talloc_move(mem_ctx, &state->wb_resp); + return state->ret; +} + +struct resp_write_state { + struct iovec iov[2]; + ssize_t ret; +}; + +static void wb_resp_write_done(struct tevent_req *subreq); + +struct tevent_req *wb_resp_write_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct tevent_queue *queue, int fd, + struct winbindd_response *wb_resp) +{ + struct tevent_req *req, *subreq; + struct resp_write_state *state; + int count = 1; + + req = tevent_req_create(mem_ctx, &state, struct resp_write_state); + if (req == NULL) { + return NULL; + } + + state->iov[0].iov_base = (void *)wb_resp; + state->iov[0].iov_len = sizeof(struct winbindd_response); + + if (wb_resp->length > sizeof(struct winbindd_response)) { + state->iov[1].iov_base = (void *)wb_resp->extra_data.data; + state->iov[1].iov_len = + wb_resp->length - sizeof(struct winbindd_response); + count = 2; + } + + subreq = writev_send(state, ev, queue, fd, true, state->iov, count); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, wb_resp_write_done, req); + return req; +} + +static void wb_resp_write_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct resp_write_state *state = tevent_req_data( + req, struct resp_write_state); + int err; + + state->ret = writev_recv(subreq, &err); + TALLOC_FREE(subreq); + if (state->ret < 0) { + tevent_req_error(req, err); + return; + } + tevent_req_done(req); +} + +ssize_t wb_resp_write_recv(struct tevent_req *req, int *err) +{ + struct resp_write_state *state = tevent_req_data( + req, struct resp_write_state); + + if (tevent_req_is_unix_error(req, err)) { + return -1; + } + return state->ret; +} + +struct wb_simple_trans_state { + struct tevent_context *ev; + int fd; + struct winbindd_response *wb_resp; +}; + +static void wb_simple_trans_write_done(struct tevent_req *subreq); +static void wb_simple_trans_read_done(struct tevent_req *subreq); + +struct tevent_req *wb_simple_trans_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct tevent_queue *queue, int fd, + struct winbindd_request *wb_req) +{ + struct tevent_req *req, *subreq; + struct wb_simple_trans_state *state; + + req = tevent_req_create(mem_ctx, &state, struct wb_simple_trans_state); + if (req == NULL) { + return NULL; + } + + wb_req->length = sizeof(struct winbindd_request); + + state->ev = ev; + state->fd = fd; + + subreq = wb_req_write_send(state, ev, queue, fd, wb_req); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, wb_simple_trans_write_done, req); + + return req; +} + +static void wb_simple_trans_write_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct wb_simple_trans_state *state = tevent_req_data( + req, struct wb_simple_trans_state); + ssize_t ret; + int err; + + ret = wb_req_write_recv(subreq, &err); + TALLOC_FREE(subreq); + if (ret == -1) { + tevent_req_error(req, err); + return; + } + subreq = wb_resp_read_send(state, state->ev, state->fd); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, wb_simple_trans_read_done, req); +} + +static void wb_simple_trans_read_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct wb_simple_trans_state *state = tevent_req_data( + req, struct wb_simple_trans_state); + ssize_t ret; + int err; + + ret = wb_resp_read_recv(subreq, state, &state->wb_resp, &err); + TALLOC_FREE(subreq); + if (ret == -1) { + tevent_req_error(req, err); + return; + } + + tevent_req_done(req); +} + +int wb_simple_trans_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, + struct winbindd_response **presponse, int *err) +{ + struct wb_simple_trans_state *state = tevent_req_data( + req, struct wb_simple_trans_state); + + if (tevent_req_is_unix_error(req, err)) { + return -1; + } + *presponse = talloc_move(mem_ctx, &state->wb_resp); + return 0; +} diff --git a/source3/lib/wb_reqtrans.h b/source3/lib/wb_reqtrans.h new file mode 100644 index 0000000000..941edf659a --- /dev/null +++ b/source3/lib/wb_reqtrans.h @@ -0,0 +1,61 @@ +/* + 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 _WB_REQTRANS_H_ +#define _WB_REQTRANS_H_ + +#include <talloc.h> +#include <tevent.h> +#include "nsswitch/winbind_struct_protocol.h" + +struct tevent_req *wb_req_read_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + int fd, size_t max_extra_data); +ssize_t wb_req_read_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, + struct winbindd_request **preq, int *err); + +struct tevent_req *wb_req_write_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct tevent_queue *queue, int fd, + struct winbindd_request *wb_req); +ssize_t wb_req_write_recv(struct tevent_req *req, int *err); + +struct tevent_req *wb_resp_read_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, int fd); +ssize_t wb_resp_read_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, + struct winbindd_response **presp, int *err); + +struct tevent_req *wb_resp_write_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct tevent_queue *queue, int fd, + struct winbindd_response *wb_resp); +ssize_t wb_resp_write_recv(struct tevent_req *req, int *err); + +struct tevent_req *wb_simple_trans_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct tevent_queue *queue, int fd, + struct winbindd_request *wb_req); +int wb_simple_trans_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, + struct winbindd_response **presponse, int *err); + +#endif /*_WB_REQTRANS_H_*/ diff --git a/source3/torture/wbc_async.h b/source3/torture/wbc_async.h index 6178bb45e9..6a49511671 100644 --- a/source3/torture/wbc_async.h +++ b/source3/torture/wbc_async.h @@ -27,7 +27,7 @@ #include <talloc.h> #include <tevent.h> #include "nsswitch/libwbclient/wbclient.h" -#include "nsswitch/libwbclient/wb_reqtrans.h" +#include "lib/wb_reqtrans.h" struct wb_context; struct winbindd_request; diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index 98cc8e6bbf..e5aeca6830 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -26,7 +26,7 @@ #include "popt_common.h" #include "winbindd.h" #include "nsswitch/winbind_client.h" -#include "../../nsswitch/libwbclient/wb_reqtrans.h" +#include "lib/wb_reqtrans.h" #include "librpc/gen_ndr/messaging.h" #include "../librpc/gen_ndr/srv_lsa.h" #include "../librpc/gen_ndr/srv_samr.h" diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index 0abe7cdc8b..0d28d9cdd8 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -29,7 +29,7 @@ #include "includes.h" #include "winbindd.h" -#include "../../nsswitch/libwbclient/wb_reqtrans.h" +#include "lib/wb_reqtrans.h" #include "librpc/gen_ndr/messaging.h" #include "secrets.h" #include "../lib/util/select.h" diff --git a/source3/wscript_build b/source3/wscript_build index 9b35af1959..dd8fffe435 100644 --- a/source3/wscript_build +++ b/source3/wscript_build @@ -384,7 +384,7 @@ WINBINDD_SRC1 = '''winbindd/winbindd.c auth/server_info_sam.c auth/user_info.c auth/user_util.c - ../nsswitch/libwbclient/wb_reqtrans.c''' + lib/wb_reqtrans.c''' WINBINDD_SRC = '''${WINBINDD_SRC1} ${TDB_VALIDATE_SRC} @@ -619,7 +619,7 @@ SMBTORTURE_SRC1 = '''torture/torture.c torture/nbio.c torture/scanner.c torture/ SMBTORTURE_SRC = '''${SMBTORTURE_SRC1} torture/wbc_async.c - ../nsswitch/libwbclient/wb_reqtrans.c''' + lib/wb_reqtrans.c''' MASKTEST_SRC = '''torture/masktest.c''' |