From 092316e22c1191aefa85c90ea4eda280b265fb86 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 6 Apr 2010 11:53:33 +0200 Subject: [PATCH 01/18] s3: fix crash in winbindd (similar to commit f8cc0e88fbbb082ead023e0cb437b1e12cf35459) Signed-off-by: Stefan Metzmacher --- source3/libsmb/async_smb.c | 11 +++++++++-- source3/rpc_client/rpc_transport_np.c | 6 ++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/source3/libsmb/async_smb.c b/source3/libsmb/async_smb.c index 07d832e..e683e37 100644 --- a/source3/libsmb/async_smb.c +++ b/source3/libsmb/async_smb.c @@ -1010,6 +1010,11 @@ static void cli_state_handler(struct event_context *event_ctx, DEBUG(11, ("cli_state_handler called with flags %d\n", flags)); + if (cli->fd == -1) { + status = NT_STATUS_CONNECTION_INVALID; + goto sock_error; + } + if (flags & EVENT_FD_WRITE) { size_t to_send; ssize_t sent; @@ -1123,6 +1128,8 @@ static void cli_state_handler(struct event_context *event_ctx, } } TALLOC_FREE(cli->fd_event); - close(cli->fd); - cli->fd = -1; + if (cli->fd != -1) { + close(cli->fd); + cli->fd = -1; + } } diff --git a/source3/rpc_client/rpc_transport_np.c b/source3/rpc_client/rpc_transport_np.c index 4ea361b..ed639d0 100644 --- a/source3/rpc_client/rpc_transport_np.c +++ b/source3/rpc_client/rpc_transport_np.c @@ -31,6 +31,12 @@ struct rpc_transport_np_state { static int rpc_transport_np_state_destructor(struct rpc_transport_np_state *s) { bool ret; + + if (s->cli->fd == -1) { + DEBUG(10, ("socket was closed, no need to send close request.\n")); + return 0; + } + ret = cli_close(s->cli, s->fnum); if (!ret) { DEBUG(1, ("rpc_transport_np_state_destructor: cli_close " -- 1.6.3.3 From f1a05ee4ad09ba97d4117c4ed5b61b00eaa06149 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 6 Apr 2010 14:04:33 +0200 Subject: [PATCH 02/18] s3:rpc_client: close the socket when pipe is broken Signed-off-by: Bo Yang (similar to commit aa70e44cd0576e5280e24cf35000369a47dd958f) Signed-off-by: Stefan Metzmacher --- source3/rpc_client/rpc_transport_sock.c | 21 ++++++++++++++++++++- 1 files changed, 20 insertions(+), 1 deletions(-) diff --git a/source3/rpc_client/rpc_transport_sock.c b/source3/rpc_client/rpc_transport_sock.c index 7115dc4..79e0426 100644 --- a/source3/rpc_client/rpc_transport_sock.c +++ b/source3/rpc_client/rpc_transport_sock.c @@ -36,6 +36,7 @@ static int rpc_transport_sock_state_destructor(struct rpc_transport_sock_state * } struct rpc_sock_read_state { + struct rpc_transport_sock_state *transp; ssize_t received; }; @@ -56,7 +57,11 @@ static struct async_req *rpc_sock_read_send(TALLOC_CTX *mem_ctx, struct rpc_sock_read_state)) { return NULL; } - + if (sock_transp->fd == -1) { + tevent_req_nterror(req, NT_STATUS_CONNECTION_INVALID); + return tevent_req_post(req, ev); + } + state->transp = sock_transp; subreq = async_recv_send(state, ev, sock_transp->fd, data, size, 0); if (subreq == NULL) { goto fail; @@ -82,6 +87,10 @@ static void rpc_sock_read_done(struct tevent_req *subreq) state->received = async_recv_recv(subreq, &err); if (state->received == -1) { + if (err == EPIPE) { + close(state->transp->fd); + state->transp->fd = -1; + } TALLOC_FREE(subreq); async_req_nterror(req, map_nt_error_from_unix(err)); return; @@ -104,6 +113,7 @@ static NTSTATUS rpc_sock_read_recv(struct async_req *req, ssize_t *preceived) } struct rpc_sock_write_state { + struct rpc_transport_sock_state *transp; ssize_t sent; }; @@ -124,6 +134,11 @@ static struct async_req *rpc_sock_write_send(TALLOC_CTX *mem_ctx, struct rpc_sock_write_state)) { return NULL; } + if (sock_transp->fd == -1) { + tevent_req_nterror(req, NT_STATUS_CONNECTION_INVALID); + return tevent_req_post(req, ev); + } + state->transp = sock_transp; subreq = async_send_send(state, ev, sock_transp->fd, data, size, 0); if (subreq == NULL) { goto fail; @@ -149,6 +164,10 @@ static void rpc_sock_write_done(struct tevent_req *subreq) state->sent = async_send_recv(subreq, &err); if (state->sent == -1) { + if (err == EPIPE) { + close(state->transp->fd); + state->transp->fd = -1; + } TALLOC_FREE(subreq); async_req_nterror(req, map_nt_error_from_unix(err)); return; -- 1.6.3.3 From 0407ddb90b6d6d29d55bf9b0583e346285d85454 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 6 Apr 2010 14:06:39 +0200 Subject: [PATCH 03/18] Fix broken pipe handling Metze is right: If we have *any* error at the socket level, we just can not continue. Also, apply some defensive programming: With this async stuff someone else might already have closed the socket. (cherry picked from commit f140bf2e6578e45b8603d4a6c5feef9a3b735804) Signed-off-by: Stefan Metzmacher --- source3/rpc_client/rpc_transport_sock.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source3/rpc_client/rpc_transport_sock.c b/source3/rpc_client/rpc_transport_sock.c index 79e0426..e6088d0 100644 --- a/source3/rpc_client/rpc_transport_sock.c +++ b/source3/rpc_client/rpc_transport_sock.c @@ -87,7 +87,7 @@ static void rpc_sock_read_done(struct tevent_req *subreq) state->received = async_recv_recv(subreq, &err); if (state->received == -1) { - if (err == EPIPE) { + if (state->transp->fd != -1) { close(state->transp->fd); state->transp->fd = -1; } @@ -164,7 +164,7 @@ static void rpc_sock_write_done(struct tevent_req *subreq) state->sent = async_send_recv(subreq, &err); if (state->sent == -1) { - if (err == EPIPE) { + if (state->transp->fd != -1) { close(state->transp->fd); state->transp->fd = -1; } -- 1.6.3.3 From 8a838edfd527ca82695bd0c2f62fac8ff0bc99ba Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 6 Apr 2010 14:14:53 +0200 Subject: [PATCH 04/18] s3: Fix infinite loop in NCACN_IP_TCP asa there is no timeout. Assume lsa_pipe_tcp is ok but network is down, then send request is ok, but select() on writeable fds loops forever since there is no response. Signed-off-by: Bo Yang (cherry picked from commit 36493bf2f6634b84c57107bcb86bcbf3e82e80fc) (similar to commit b58b359881c91ec382cfa1d6ba3007b8354b29cb) Signed-off-by: Stefan Metzmacher --- source3/rpc_client/rpc_transport_sock.c | 16 ++++++++++++++++ 1 files changed, 16 insertions(+), 0 deletions(-) diff --git a/source3/rpc_client/rpc_transport_sock.c b/source3/rpc_client/rpc_transport_sock.c index e6088d0..e0f7bcb 100644 --- a/source3/rpc_client/rpc_transport_sock.c +++ b/source3/rpc_client/rpc_transport_sock.c @@ -24,6 +24,7 @@ struct rpc_transport_sock_state { int fd; + int timeout; }; static int rpc_transport_sock_state_destructor(struct rpc_transport_sock_state *s) @@ -52,6 +53,7 @@ static struct async_req *rpc_sock_read_send(TALLOC_CTX *mem_ctx, struct async_req *result; struct tevent_req *subreq; struct rpc_sock_read_state *state; + struct timeval endtime; if (!async_req_setup(mem_ctx, &result, &state, struct rpc_sock_read_state)) { @@ -62,10 +64,16 @@ static struct async_req *rpc_sock_read_send(TALLOC_CTX *mem_ctx, return tevent_req_post(req, ev); } state->transp = sock_transp; + endtime = timeval_current_ofs(0, sock_transp->timeout * 1000); subreq = async_recv_send(state, ev, sock_transp->fd, data, size, 0); if (subreq == NULL) { goto fail; } + + if (!tevent_req_set_endtime(subreq, ev, endtime)) { + goto fail; + } + tevent_req_set_callback(subreq, rpc_sock_read_done, result); return result; fail: @@ -129,6 +137,7 @@ static struct async_req *rpc_sock_write_send(TALLOC_CTX *mem_ctx, struct async_req *result; struct tevent_req *subreq; struct rpc_sock_write_state *state; + struct timeval endtime; if (!async_req_setup(mem_ctx, &result, &state, struct rpc_sock_write_state)) { @@ -139,10 +148,16 @@ static struct async_req *rpc_sock_write_send(TALLOC_CTX *mem_ctx, return tevent_req_post(req, ev); } state->transp = sock_transp; + endtime = timeval_current_ofs(0, sock_transp->timeout * 1000); subreq = async_send_send(state, ev, sock_transp->fd, data, size, 0); if (subreq == NULL) { goto fail; } + + if (!tevent_req_set_endtime(subreq, ev, endtime)) { + goto fail; + } + tevent_req_set_callback(subreq, rpc_sock_write_done, result); return result; fail: @@ -207,6 +222,7 @@ NTSTATUS rpc_transport_sock_init(TALLOC_CTX *mem_ctx, int fd, result->priv = state; state->fd = fd; + state->timeout = 10000; /* 10 seconds. */ talloc_set_destructor(state, rpc_transport_sock_state_destructor); result->trans_send = NULL; -- 1.6.3.3 From ea59c902a73989e410265e6c7a9a8018dc07920c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 6 Apr 2010 12:22:54 +0200 Subject: [PATCH 05/18] s3:rpc_transport_np: handle trans rdata like the output of a normal read Inspired by bug #7159. metze (cherry picked from commit 911287285cc4c8485b75edfad3c1ece901a69b0b) (cherry picked from commit e2739a2bf37e654c37cbea6e510f63a7ce4adfea) Signed-off-by: Stefan Metzmacher --- source3/rpc_client/rpc_transport_np.c | 17 +++++++++++++++++ 1 files changed, 17 insertions(+), 0 deletions(-) diff --git a/source3/rpc_client/rpc_transport_np.c b/source3/rpc_client/rpc_transport_np.c index ed639d0..f502ced 100644 --- a/source3/rpc_client/rpc_transport_np.c +++ b/source3/rpc_client/rpc_transport_np.c @@ -214,6 +214,7 @@ static NTSTATUS rpc_np_read_recv(struct async_req *req, ssize_t *preceived) struct rpc_np_trans_state { uint16_t setup[2]; + uint32_t max_rdata_len; uint8_t *rdata; uint32_t rdata_len; }; @@ -236,6 +237,8 @@ static struct async_req *rpc_np_trans_send(TALLOC_CTX *mem_ctx, return NULL; } + state->max_rdata_len = max_rdata_len; + SSVAL(state->setup+0, 0, TRANSACT_DCERPCCMD); SSVAL(state->setup+1, 0, np_transport->fnum); @@ -266,10 +269,24 @@ static void rpc_np_trans_done(struct async_req *subreq) status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, &state->rdata, &state->rdata_len); TALLOC_FREE(subreq); + if (NT_STATUS_EQUAL(status, NT_STATUS_BUFFER_TOO_SMALL)) { + status = NT_STATUS_OK; + } if (!NT_STATUS_IS_OK(status)) { async_req_nterror(req, status); return; } + + if (state->rdata_len > state->max_rdata_len) { + async_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); + return; + } + + if (state->rdata_len == 0) { + async_req_nterror(req, NT_STATUS_PIPE_BROKEN); + return; + } + async_req_done(req); } -- 1.6.3.3 From f1767720fd0c617a9d8ab53f44ddedbf1a25bd91 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 29 Mar 2010 18:23:40 +0200 Subject: [PATCH 06/18] s3:libsmb: don't let cli_shutdown() segfault with a NULL cli_state metze (similar to commit 47e10ab9a85960c78af807b66b99bcd139713644) (cherry picked from commit 957c0d4a5ee67ac70e576155a0f2f6f84cdb1596) Signed-off-by: Stefan Metzmacher --- source3/libsmb/clientgen.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c index 356db57..5dc43e9 100644 --- a/source3/libsmb/clientgen.c +++ b/source3/libsmb/clientgen.c @@ -599,6 +599,10 @@ void cli_nt_pipes_close(struct cli_state *cli) void cli_shutdown(struct cli_state *cli) { + if (cli == NULL) { + return; + } + if (cli->prev == NULL) { /* * Possible head of a DFS list, -- 1.6.3.3 From b2fae52a64f059c5761d424b4181adf60898659e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 25 Mar 2010 13:20:56 +0100 Subject: [PATCH 07/18] s3:libsmb: add cli_state_is_connected() function metze (cherry picked from commit d7bf30ef92031ffddcde3680b38e602510bcae24) (cherry picked from commit 589f73924273e8a9b54669f42a92381661dcb33f) Signed-off-by: Stefan Metzmacher --- source3/include/proto.h | 1 + source3/libsmb/clierror.c | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 0 deletions(-) diff --git a/source3/include/proto.h b/source3/include/proto.h index f078844..0b84694 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -2456,6 +2456,7 @@ bool cli_is_dos_error(struct cli_state *cli); NTSTATUS cli_get_nt_error(struct cli_state *cli); void cli_set_nt_error(struct cli_state *cli, NTSTATUS status); void cli_reset_error(struct cli_state *cli); +bool cli_state_is_connected(struct cli_state *cli); /* The following definitions come from libsmb/clifile.c */ diff --git a/source3/libsmb/clierror.c b/source3/libsmb/clierror.c index 54f8a7a..015afb1 100644 --- a/source3/libsmb/clierror.c +++ b/source3/libsmb/clierror.c @@ -359,3 +359,21 @@ void cli_reset_error(struct cli_state *cli) SSVAL(cli->inbuf,smb_err,0); } } + +bool cli_state_is_connected(struct cli_state *cli) +{ + if (cli == NULL) { + return false; + } + + if (!cli->initialised) { + return false; + } + + if (cli->fd == -1) { + return false; + } + + return true; +} + -- 1.6.3.3 From bdc2ca7b2393c0370af56ff663d6ec462834183e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 6 Apr 2010 12:23:39 +0200 Subject: [PATCH 08/18] s3:rpc_transport_np: use cli_state_is_connected() helper metze (cherry picked from commit b862351da8624df893ec77e020a456c1d23c58ed) (cherry picked from commit 8c2f4426ce178ac33748cfba01532ec2fd205710) Signed-off-by: Stefan Metzmacher --- source3/rpc_client/rpc_transport_np.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/source3/rpc_client/rpc_transport_np.c b/source3/rpc_client/rpc_transport_np.c index f502ced..1997e9c 100644 --- a/source3/rpc_client/rpc_transport_np.c +++ b/source3/rpc_client/rpc_transport_np.c @@ -32,7 +32,7 @@ static int rpc_transport_np_state_destructor(struct rpc_transport_np_state *s) { bool ret; - if (s->cli->fd == -1) { + if (!cli_state_is_connected(s->cli)) { DEBUG(10, ("socket was closed, no need to send close request.\n")); return 0; } -- 1.6.3.3 From 784ff7e44185cef509004c0e48ccff647d12272e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 29 Mar 2010 14:58:19 +0200 Subject: [PATCH 09/18] s3:rpc_client: don't mix layers and keep a reference to cli_state in the caller We should not rely on the backend to have a reference to the cli_state. This will make it possible for the backend to set its cli_state reference to NULL, when the transport is dead. metze (cherry picked from commit dc09b12681ea0e6d4c2b0f1c99dfeb1f23019c65) (cherry picked from commit 1e2e47da82aeb249dce431541738a62cb139aebb) Signed-off-by: Stefan Metzmacher --- source3/rpc_client/cli_pipe.c | 25 +++++++++++++++++-------- 1 files changed, 17 insertions(+), 8 deletions(-) diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 323f861..cc0c66c 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -3464,14 +3464,14 @@ NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path, return status; } -static int rpc_pipe_client_np_destructor(struct rpc_pipe_client *p) -{ +struct rpc_pipe_client_np_ref { struct cli_state *cli; + struct rpc_pipe_client *pipe; +}; - cli = rpc_pipe_np_smb_conn(p); - if (cli != NULL) { - DLIST_REMOVE(cli->pipe_list, p); - } +static int rpc_pipe_client_np_ref_destructor(struct rpc_pipe_client_np_ref *np_ref) +{ + DLIST_REMOVE(np_ref->cli->pipe_list, np_ref->pipe); return 0; } @@ -3494,6 +3494,7 @@ static NTSTATUS rpc_pipe_open_np(struct cli_state *cli, { struct rpc_pipe_client *result; NTSTATUS status; + struct rpc_pipe_client_np_ref *np_ref; /* sanity check to protect against crashes */ @@ -3530,8 +3531,16 @@ static NTSTATUS rpc_pipe_open_np(struct cli_state *cli, result->transport->transport = NCACN_NP; - DLIST_ADD(cli->pipe_list, result); - talloc_set_destructor(result, rpc_pipe_client_np_destructor); + np_ref = talloc(result->transport, struct rpc_pipe_client_np_ref); + if (np_ref == NULL) { + TALLOC_FREE(result); + return NT_STATUS_NO_MEMORY; + } + np_ref->cli = cli; + np_ref->pipe = result; + + DLIST_ADD(np_ref->cli->pipe_list, np_ref->pipe); + talloc_set_destructor(np_ref, rpc_pipe_client_np_ref_destructor); *presult = result; return NT_STATUS_OK; -- 1.6.3.3 From f12ebe1880d369359b56fd89971c940645a8809c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 6 Apr 2010 14:26:29 +0200 Subject: [PATCH 10/18] s3:rpc_client: add rpccli_is_connected() metze (cherry picked from commit 4f41b53487ac9bc96c7960e8edab464558656373) (similar to commit 958b49323968740e2cbf69dc2a0a5dd57d5bcf87) Signed-off-by: Stefan Metzmacher --- source3/include/client.h | 3 + source3/include/proto.h | 1 + source3/rpc_client/cli_pipe.c | 13 +++++ source3/rpc_client/rpc_transport_np.c | 78 +++++++++++++++++++++++++++++- source3/rpc_client/rpc_transport_smbd.c | 82 ++++++++++++++++++++++++++++-- source3/rpc_client/rpc_transport_sock.c | 46 ++++++++++++------ 6 files changed, 201 insertions(+), 22 deletions(-) diff --git a/source3/include/client.h b/source3/include/client.h index 1914210..bdc6aeb 100644 --- a/source3/include/client.h +++ b/source3/include/client.h @@ -110,6 +110,9 @@ struct rpc_cli_transport { */ NTSTATUS (*trans_recv)(struct async_req *req, TALLOC_CTX *mem_ctx, uint8_t **prdata, uint32_t *prdata_len); + + bool (*is_connected)(void *priv); + void *priv; }; diff --git a/source3/include/proto.h b/source3/include/proto.h index 0b84694..b22c530 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -5275,6 +5275,7 @@ NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli, struct cli_pipe_auth_data *auth); unsigned int rpccli_set_timeout(struct rpc_pipe_client *cli, unsigned int timeout); +bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli); bool rpccli_get_pwd_hash(struct rpc_pipe_client *cli, uint8_t nt_hash[16]); NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx, struct cli_pipe_auth_data **presult); diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index cc0c66c..94e714d 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -2961,6 +2961,19 @@ unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli, return cli_set_timeout(cli, timeout); } +bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli) +{ + if (rpc_cli == NULL) { + return false; + } + + if (rpc_cli->transport == NULL) { + return false; + } + + return rpc_cli->transport->is_connected(rpc_cli->transport->priv); +} + bool rpccli_get_pwd_hash(struct rpc_pipe_client *rpc_cli, uint8_t nt_hash[16]) { struct cli_state *cli; diff --git a/source3/rpc_client/rpc_transport_np.c b/source3/rpc_client/rpc_transport_np.c index 1997e9c..ae0c326 100644 --- a/source3/rpc_client/rpc_transport_np.c +++ b/source3/rpc_client/rpc_transport_np.c @@ -28,11 +28,30 @@ struct rpc_transport_np_state { uint16_t fnum; }; +static bool rpc_np_is_connected(void *priv) +{ + struct rpc_transport_np_state *np_transport = talloc_get_type_abort( + priv, struct rpc_transport_np_state); + bool ok; + + if (np_transport->cli == NULL) { + return false; + } + + ok = cli_state_is_connected(np_transport->cli); + if (!ok) { + np_transport->cli = NULL; + return false; + } + + return true; +} + static int rpc_transport_np_state_destructor(struct rpc_transport_np_state *s) { bool ret; - if (!cli_state_is_connected(s->cli)) { + if (!rpc_np_is_connected(s)) { DEBUG(10, ("socket was closed, no need to send close request.\n")); return 0; } @@ -51,6 +70,7 @@ static int rpc_transport_np_state_destructor(struct rpc_transport_np_state *s) } struct rpc_np_write_state { + struct rpc_transport_np_state *np_transport; size_t size; size_t written; }; @@ -66,13 +86,26 @@ static struct async_req *rpc_np_write_send(TALLOC_CTX *mem_ctx, priv, struct rpc_transport_np_state); struct async_req *result, *subreq; struct rpc_np_write_state *state; + bool ok; if (!async_req_setup(mem_ctx, &result, &state, struct rpc_np_write_state)) { return NULL; } + + ok = rpc_np_is_connected(np_transport); + if (!ok) { + ok = async_post_ntstatus(result, ev, NT_STATUS_CONNECTION_INVALID); + if (!ok) { + goto fail; + } + return result; + } + + state->np_transport = np_transport; state->size = size; + subreq = cli_write_andx_send(mem_ctx, ev, np_transport->cli, np_transport->fnum, 8, /* 8 means message mode. */ @@ -99,6 +132,7 @@ static void rpc_np_write_done(struct async_req *subreq) status = cli_write_andx_recv(subreq, &state->written); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { + state->np_transport->cli = NULL; async_req_nterror(req, status); return; } @@ -119,6 +153,7 @@ static NTSTATUS rpc_np_write_recv(struct async_req *req, ssize_t *pwritten) } struct rpc_np_read_state { + struct rpc_transport_np_state *np_transport; uint8_t *data; size_t size; ssize_t received; @@ -135,11 +170,23 @@ static struct async_req *rpc_np_read_send(TALLOC_CTX *mem_ctx, priv, struct rpc_transport_np_state); struct async_req *result, *subreq; struct rpc_np_read_state *state; + bool ok; if (!async_req_setup(mem_ctx, &result, &state, struct rpc_np_read_state)) { return NULL; } + + ok = rpc_np_is_connected(np_transport); + if (!ok) { + ok = async_post_ntstatus(result, ev, NT_STATUS_CONNECTION_INVALID); + if (!ok) { + goto fail; + } + return result; + } + + state->np_transport = np_transport; state->data = data; state->size = size; @@ -178,18 +225,21 @@ static void rpc_np_read_done(struct async_req *subreq) } if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(subreq); + state->np_transport->cli = NULL; async_req_nterror(req, status); return; } if (state->received > state->size) { TALLOC_FREE(subreq); + state->np_transport->cli = NULL; async_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); return; } if (state->received == 0) { TALLOC_FREE(subreq); + state->np_transport->cli = NULL; async_req_nterror(req, NT_STATUS_PIPE_BROKEN); return; } @@ -213,6 +263,7 @@ static NTSTATUS rpc_np_read_recv(struct async_req *req, ssize_t *preceived) } struct rpc_np_trans_state { + struct rpc_transport_np_state *np_transport; uint16_t setup[2]; uint32_t max_rdata_len; uint8_t *rdata; @@ -231,12 +282,23 @@ static struct async_req *rpc_np_trans_send(TALLOC_CTX *mem_ctx, priv, struct rpc_transport_np_state); struct async_req *result, *subreq; struct rpc_np_trans_state *state; + bool ok; if (!async_req_setup(mem_ctx, &result, &state, struct rpc_np_trans_state)) { return NULL; } + ok = rpc_np_is_connected(np_transport); + if (!ok) { + ok = async_post_ntstatus(result, ev, NT_STATUS_CONNECTION_INVALID); + if (!ok) { + goto fail; + } + return result; + } + + state->np_transport = np_transport; state->max_rdata_len = max_rdata_len; SSVAL(state->setup+0, 0, TRANSACT_DCERPCCMD); @@ -273,16 +335,19 @@ static void rpc_np_trans_done(struct async_req *subreq) status = NT_STATUS_OK; } if (!NT_STATUS_IS_OK(status)) { + state->np_transport->cli = NULL; async_req_nterror(req, status); return; } if (state->rdata_len > state->max_rdata_len) { + state->np_transport->cli = NULL; async_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); return; } if (state->rdata_len == 0) { + state->np_transport->cli = NULL; async_req_nterror(req, NT_STATUS_PIPE_BROKEN); return; } @@ -319,12 +384,22 @@ struct async_req *rpc_transport_np_init_send(TALLOC_CTX *mem_ctx, { struct async_req *result, *subreq; struct rpc_transport_np_init_state *state; + bool ok; if (!async_req_setup(mem_ctx, &result, &state, struct rpc_transport_np_init_state)) { return NULL; } + ok = cli_state_is_connected(cli); + if (!ok) { + ok = async_post_ntstatus(result, ev, NT_STATUS_CONNECTION_INVALID); + if (!ok) { + goto fail; + } + return result; + } + state->transport = talloc(state, struct rpc_cli_transport); if (state->transport == NULL) { goto fail; @@ -394,6 +469,7 @@ NTSTATUS rpc_transport_np_init_recv(struct async_req *req, state->transport->read_recv = rpc_np_read_recv; state->transport->trans_send = rpc_np_trans_send; state->transport->trans_recv = rpc_np_trans_recv; + state->transport->is_connected = rpc_np_is_connected; *presult = talloc_move(mem_ctx, &state->transport); return NT_STATUS_OK; diff --git a/source3/rpc_client/rpc_transport_smbd.c b/source3/rpc_client/rpc_transport_smbd.c index 823f216..262caf9 100644 --- a/source3/rpc_client/rpc_transport_smbd.c +++ b/source3/rpc_client/rpc_transport_smbd.c @@ -429,8 +429,53 @@ NTSTATUS rpc_cli_smbd_conn_init(TALLOC_CTX *mem_ctx, return status; } +static void rpc_smbd_disconnect(struct rpc_transport_smbd_state *transp) +{ + if (transp == NULL) { + return; + } + + if (transp->conn == NULL) { + return; + } + + if (transp->conn->cli == NULL) { + return; + } + + if (transp->conn->cli->fd != -1) { + close(transp->conn->cli->fd); + transp->conn->cli->fd = -1; + } + + transp->conn = NULL; +} + +static bool rpc_smbd_is_connected(void *priv) +{ + struct rpc_transport_smbd_state *transp = talloc_get_type_abort( + priv, struct rpc_transport_smbd_state); + bool ok; + + if (transp->conn == NULL) { + return false; + } + + if (transp->sub_transp == NULL) { + return false; + } + + ok = transp->sub_transp->is_connected(transp->sub_transp->priv); + if (!ok) { + rpc_smbd_disconnect(transp); + return false; + } + + return true; +} + struct rpc_smbd_write_state { - struct rpc_cli_transport *sub_transp; + struct rpc_transport_smbd_state *transp; ssize_t written; }; @@ -445,12 +490,23 @@ static struct async_req *rpc_smbd_write_send(TALLOC_CTX *mem_ctx, priv, struct rpc_transport_smbd_state); struct async_req *result, *subreq; struct rpc_smbd_write_state *state; + bool ok; if (!async_req_setup(mem_ctx, &result, &state, struct rpc_smbd_write_state)) { return NULL; } - state->sub_transp = transp->sub_transp; + + ok = rpc_smbd_is_connected(transp); + if (!ok) { + ok = async_post_ntstatus(result, ev, NT_STATUS_CONNECTION_INVALID); + if (!ok) { + goto fail; + } + return result; + } + + state->transp = transp; subreq = transp->sub_transp->write_send(state, ev, data, size, transp->sub_transp->priv); @@ -480,9 +536,10 @@ static void rpc_smbd_write_done(struct async_req *subreq) req->private_data, struct rpc_smbd_write_state); NTSTATUS status; - status = state->sub_transp->write_recv(subreq, &state->written); + status = state->transp->sub_transp->write_recv(subreq, &state->written); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { + rpc_smbd_disconnect(state->transp); async_req_nterror(req, status); return; } @@ -503,7 +560,7 @@ static NTSTATUS rpc_smbd_write_recv(struct async_req *req, ssize_t *pwritten) } struct rpc_smbd_read_state { - struct rpc_cli_transport *sub_transp; + struct rpc_transport_smbd_state *transp; ssize_t received; }; @@ -518,12 +575,23 @@ static struct async_req *rpc_smbd_read_send(TALLOC_CTX *mem_ctx, priv, struct rpc_transport_smbd_state); struct async_req *result, *subreq; struct rpc_smbd_read_state *state; + bool ok; if (!async_req_setup(mem_ctx, &result, &state, struct rpc_smbd_read_state)) { return NULL; } - state->sub_transp = transp->sub_transp; + + ok = rpc_smbd_is_connected(transp); + if (!ok) { + ok = async_post_ntstatus(result, ev, NT_STATUS_CONNECTION_INVALID); + if (!ok) { + goto fail; + } + return result; + } + + state->transp = transp; subreq = transp->sub_transp->read_send(state, ev, data, size, transp->sub_transp->priv); @@ -553,9 +621,10 @@ static void rpc_smbd_read_done(struct async_req *subreq) req->private_data, struct rpc_smbd_read_state); NTSTATUS status; - status = state->sub_transp->read_recv(subreq, &state->received); + status = state->transp->sub_transp->read_recv(subreq, &state->received); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { + rpc_smbd_disconnect(state->transp); async_req_nterror(req, status); return; } @@ -663,6 +732,7 @@ NTSTATUS rpc_transport_smbd_init_recv(struct async_req *req, state->transport->read_recv = rpc_smbd_read_recv; state->transport->trans_send = NULL; state->transport->trans_recv = NULL; + state->transport->is_connected = rpc_smbd_is_connected; *presult = talloc_move(mem_ctx, &state->transport); return NT_STATUS_OK; diff --git a/source3/rpc_client/rpc_transport_sock.c b/source3/rpc_client/rpc_transport_sock.c index e0f7bcb..95e16c3 100644 --- a/source3/rpc_client/rpc_transport_sock.c +++ b/source3/rpc_client/rpc_transport_sock.c @@ -27,15 +27,32 @@ struct rpc_transport_sock_state { int timeout; }; -static int rpc_transport_sock_state_destructor(struct rpc_transport_sock_state *s) +static void rpc_sock_disconnect(struct rpc_transport_sock_state *s) { if (s->fd != -1) { close(s->fd); s->fd = -1; } +} + +static int rpc_transport_sock_state_destructor(struct rpc_transport_sock_state *s) +{ + rpc_sock_disconnect(s); return 0; } +static bool rpc_sock_is_connected(void *priv) +{ + struct rpc_transport_sock_state *sock_transp = talloc_get_type_abort( + priv, struct rpc_transport_sock_state); + + if (sock_transp->fd == -1) { + return false; + } + + return true; +} + struct rpc_sock_read_state { struct rpc_transport_sock_state *transp; ssize_t received; @@ -59,9 +76,11 @@ static struct async_req *rpc_sock_read_send(TALLOC_CTX *mem_ctx, struct rpc_sock_read_state)) { return NULL; } - if (sock_transp->fd == -1) { - tevent_req_nterror(req, NT_STATUS_CONNECTION_INVALID); - return tevent_req_post(req, ev); + if (!rpc_sock_is_connected(sock_transp)) { + if (!async_post_ntstatus(result, ev, NT_STATUS_CONNECTION_INVALID)) { + goto fail; + } + return result; } state->transp = sock_transp; endtime = timeval_current_ofs(0, sock_transp->timeout * 1000); @@ -95,11 +114,8 @@ static void rpc_sock_read_done(struct tevent_req *subreq) state->received = async_recv_recv(subreq, &err); if (state->received == -1) { - if (state->transp->fd != -1) { - close(state->transp->fd); - state->transp->fd = -1; - } TALLOC_FREE(subreq); + rpc_sock_disconnect(state->transp); async_req_nterror(req, map_nt_error_from_unix(err)); return; } @@ -143,9 +159,11 @@ static struct async_req *rpc_sock_write_send(TALLOC_CTX *mem_ctx, struct rpc_sock_write_state)) { return NULL; } - if (sock_transp->fd == -1) { - tevent_req_nterror(req, NT_STATUS_CONNECTION_INVALID); - return tevent_req_post(req, ev); + if (!rpc_sock_is_connected(sock_transp)) { + if (!async_post_ntstatus(result, ev, NT_STATUS_CONNECTION_INVALID)) { + goto fail; + } + return result; } state->transp = sock_transp; endtime = timeval_current_ofs(0, sock_transp->timeout * 1000); @@ -179,11 +197,8 @@ static void rpc_sock_write_done(struct tevent_req *subreq) state->sent = async_send_recv(subreq, &err); if (state->sent == -1) { - if (state->transp->fd != -1) { - close(state->transp->fd); - state->transp->fd = -1; - } TALLOC_FREE(subreq); + rpc_sock_disconnect(state->transp); async_req_nterror(req, map_nt_error_from_unix(err)); return; } @@ -231,6 +246,7 @@ NTSTATUS rpc_transport_sock_init(TALLOC_CTX *mem_ctx, int fd, result->write_recv = rpc_sock_write_recv; result->read_send = rpc_sock_read_send; result->read_recv = rpc_sock_read_recv; + result->is_connected = rpc_sock_is_connected; *presult = result; return NT_STATUS_OK; -- 1.6.3.3 From e87736e916e62881c0eb5f1f07d9e4840eb127e3 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 6 Apr 2010 14:31:17 +0200 Subject: [PATCH 11/18] s3:rpc_client: add set_timeout hook to rpc_cli_transport metze (cherry picked from commit 99664ad15460530b6fb44957b6c57823f09884bf) (cherry picked from commit 89164eb8363ffc0b951256578be48d37ddba46b1) Signed-off-by: Stefan Metzmacher --- source3/include/client.h | 1 + source3/rpc_client/cli_pipe.c | 9 ++++++--- source3/rpc_client/rpc_transport_np.c | 19 +++++++++++++++++++ source3/rpc_client/rpc_transport_smbd.c | 19 +++++++++++++++++++ source3/rpc_client/rpc_transport_sock.c | 20 ++++++++++++++++++++ 5 files changed, 65 insertions(+), 3 deletions(-) diff --git a/source3/include/client.h b/source3/include/client.h index bdc6aeb..d80989d 100644 --- a/source3/include/client.h +++ b/source3/include/client.h @@ -112,6 +112,7 @@ struct rpc_cli_transport { uint8_t **prdata, uint32_t *prdata_len); bool (*is_connected)(void *priv); + unsigned int (*set_timeout)(void *priv, unsigned int timeout); void *priv; }; diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 94e714d..9ce090f 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -2953,12 +2953,15 @@ NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli, unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli, unsigned int timeout) { - struct cli_state *cli = rpc_pipe_np_smb_conn(rpc_cli); + if (rpc_cli->transport == NULL) { + return 0; + } - if (cli == NULL) { + if (rpc_cli->transport->set_timeout == NULL) { return 0; } - return cli_set_timeout(cli, timeout); + + return rpc_cli->transport->set_timeout(rpc_cli->transport->priv, timeout); } bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli) diff --git a/source3/rpc_client/rpc_transport_np.c b/source3/rpc_client/rpc_transport_np.c index ae0c326..ee6d458 100644 --- a/source3/rpc_client/rpc_transport_np.c +++ b/source3/rpc_client/rpc_transport_np.c @@ -47,6 +47,24 @@ static bool rpc_np_is_connected(void *priv) return true; } +static unsigned int rpc_np_set_timeout(void *priv, unsigned int timeout) +{ + struct rpc_transport_np_state *np_transport = talloc_get_type_abort( + priv, struct rpc_transport_np_state); + bool ok; + + if (np_transport->cli == NULL) { + return false; + } + + ok = rpc_np_is_connected(np_transport); + if (!ok) { + return 0; + } + + return cli_set_timeout(np_transport->cli, timeout); +} + static int rpc_transport_np_state_destructor(struct rpc_transport_np_state *s) { bool ret; @@ -470,6 +488,7 @@ NTSTATUS rpc_transport_np_init_recv(struct async_req *req, state->transport->trans_send = rpc_np_trans_send; state->transport->trans_recv = rpc_np_trans_recv; state->transport->is_connected = rpc_np_is_connected; + state->transport->set_timeout = rpc_np_set_timeout; *presult = talloc_move(mem_ctx, &state->transport); return NT_STATUS_OK; diff --git a/source3/rpc_client/rpc_transport_smbd.c b/source3/rpc_client/rpc_transport_smbd.c index 262caf9..f461fb8 100644 --- a/source3/rpc_client/rpc_transport_smbd.c +++ b/source3/rpc_client/rpc_transport_smbd.c @@ -474,6 +474,24 @@ static bool rpc_smbd_is_connected(void *priv) return true; } +static unsigned int rpc_smbd_set_timeout(void *priv, unsigned int timeout) +{ + struct rpc_transport_smbd_state *transp = talloc_get_type_abort( + priv, struct rpc_transport_smbd_state); + bool ok; + + ok = rpc_smbd_is_connected(transp); + if (!ok) { + return 0; + } + + if (transp->sub_transp->set_timeout == NULL) { + return 0; + } + + return transp->sub_transp->set_timeout(transp->sub_transp->priv, timeout); +} + struct rpc_smbd_write_state { struct rpc_transport_smbd_state *transp; ssize_t written; @@ -733,6 +751,7 @@ NTSTATUS rpc_transport_smbd_init_recv(struct async_req *req, state->transport->trans_send = NULL; state->transport->trans_recv = NULL; state->transport->is_connected = rpc_smbd_is_connected; + state->transport->set_timeout = rpc_smbd_set_timeout; *presult = talloc_move(mem_ctx, &state->transport); return NT_STATUS_OK; diff --git a/source3/rpc_client/rpc_transport_sock.c b/source3/rpc_client/rpc_transport_sock.c index 95e16c3..442f309 100644 --- a/source3/rpc_client/rpc_transport_sock.c +++ b/source3/rpc_client/rpc_transport_sock.c @@ -53,6 +53,25 @@ static bool rpc_sock_is_connected(void *priv) return true; } +static unsigned int rpc_sock_set_timeout(void *priv, unsigned int timeout) +{ + struct rpc_transport_sock_state *sock_transp = talloc_get_type_abort( + priv, struct rpc_transport_sock_state); + int orig_timeout; + bool ok; + + ok = rpc_sock_is_connected(sock_transp); + if (!ok) { + return 0; + } + + orig_timeout = sock_transp->timeout; + + sock_transp->timeout = timeout; + + return orig_timeout; +} + struct rpc_sock_read_state { struct rpc_transport_sock_state *transp; ssize_t received; @@ -247,6 +266,7 @@ NTSTATUS rpc_transport_sock_init(TALLOC_CTX *mem_ctx, int fd, result->read_send = rpc_sock_read_send; result->read_recv = rpc_sock_read_recv; result->is_connected = rpc_sock_is_connected; + result->set_timeout = rpc_sock_set_timeout; *presult = result; return NT_STATUS_OK; -- 1.6.3.3 From 3bde737e419ca673525181ed8597ff3cab8b27e5 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sun, 28 Mar 2010 19:34:34 +0200 Subject: [PATCH 12/18] s3:rpc_client: return at least 10 sec as old timeout in rpccli_set_timeout() instead of 0 metze (cherry picked from commit 3e70da3f470eeb122f95477fb48d89939f501b3e) (cherry picked from commit 60861fba533027b6c9a0ff704b95dcf631ea3ca3) Signed-off-by: Stefan Metzmacher --- source3/rpc_client/cli_pipe.c | 15 ++++++++++++--- 1 files changed, 12 insertions(+), 3 deletions(-) diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 9ce090f..22794bc 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -2950,18 +2950,27 @@ NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli, return status; } +#define RPCCLI_DEFAULT_TIMEOUT 10000 /* 10 seconds. */ + unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli, unsigned int timeout) { + unsigned int old; + if (rpc_cli->transport == NULL) { - return 0; + return RPCCLI_DEFAULT_TIMEOUT; } if (rpc_cli->transport->set_timeout == NULL) { - return 0; + return RPCCLI_DEFAULT_TIMEOUT; + } + + old = rpc_cli->transport->set_timeout(rpc_cli->transport->priv, timeout); + if (old == 0) { + return RPCCLI_DEFAULT_TIMEOUT; } - return rpc_cli->transport->set_timeout(rpc_cli->transport->priv, timeout); + return old; } bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli) -- 1.6.3.3 From 9cd32f56797ba5a19faffd151d35baa64b01c3be Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 25 Mar 2010 15:14:02 +0100 Subject: [PATCH 13/18] s3:winbindd_cm: use cli_state_is_connected() helper function metze (cherry picked from commit 408a3eb35a0e61b5d66a3b48ebbd1a6796672d0f) (cherry picked from commit 00a93190d2cae31cd2213b810ea348c055670399) Signed-off-by: Stefan Metzmacher --- source3/winbindd/winbindd_cm.c | 18 ++++-------------- 1 files changed, 4 insertions(+), 14 deletions(-) diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 481d985..ce7f543 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -1592,21 +1592,11 @@ void close_conns_after_fork(void) static bool connection_ok(struct winbindd_domain *domain) { - if (domain->conn.cli == NULL) { - DEBUG(8, ("connection_ok: Connection to %s for domain %s has NULL " - "cli!\n", domain->dcname, domain->name)); - return False; - } - - if (!domain->conn.cli->initialised) { - DEBUG(3, ("connection_ok: Connection to %s for domain %s was never " - "initialised!\n", domain->dcname, domain->name)); - return False; - } + bool ok; - if (domain->conn.cli->fd == -1) { - DEBUG(3, ("connection_ok: Connection to %s for domain %s has died or was " - "never started (fd == -1)\n", + ok = cli_state_is_connected(domain->conn.cli); + if (!ok) { + DEBUG(3, ("connection_ok: Connection to %s for domain %s is not connected\n", domain->dcname, domain->name)); return False; } -- 1.6.3.3 From 556bc2effa2cb07354035a27352c831d895f4db8 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 6 Apr 2010 14:42:04 +0200 Subject: [PATCH 14/18] s3:winbindd_cm: use rpccli_is_connected() helper function metze (cherry picked from commit d980c06a994d032a833adc8d56d2f2c037f8fdaf) (cherry picked from commit aa7d54ed04585a183a88363406ed7f3244b24d85) Signed-off-by: Stefan Metzmacher --- source3/winbindd/winbindd_cm.c | 9 +++++---- 1 files changed, 5 insertions(+), 4 deletions(-) diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index ce7f543..73f431a 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -2003,7 +2003,7 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, conn = &domain->conn; - if (conn->samr_pipe != NULL) { + if (rpccli_is_connected(conn->samr_pipe)) { goto done; } @@ -2187,7 +2187,8 @@ NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain, if (conn->lsa_pipe_tcp && conn->lsa_pipe_tcp->transport->transport == NCACN_IP_TCP && - conn->lsa_pipe_tcp->auth->auth_level == PIPE_AUTH_LEVEL_PRIVACY) { + conn->lsa_pipe_tcp->auth->auth_level == PIPE_AUTH_LEVEL_PRIVACY && + rpccli_is_connected(conn->lsa_pipe_tcp)) { goto done; } @@ -2229,7 +2230,7 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, conn = &domain->conn; - if (conn->lsa_pipe != NULL) { + if (rpccli_is_connected(conn->lsa_pipe)) { goto done; } @@ -2360,7 +2361,7 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, conn = &domain->conn; - if (conn->netlogon_pipe != NULL) { + if (rpccli_is_connected(conn->netlogon_pipe)) { *cli = conn->netlogon_pipe; return NT_STATUS_OK; } -- 1.6.3.3 From fad62926ca57d9fadabbd2c532a077158b33971a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 25 Mar 2010 15:17:07 +0100 Subject: [PATCH 15/18] s3:winbindd: consistently use TALLOC_FREE(conn->foo_pipe) is we create a new connection metze (cherry picked from commit 4f391fedac7111683d13f2d79fee7c0dbc27f86e) (cherry picked from commit c462e54142c00fdd81c2847d16a75119b1cc89fc) Signed-off-by: Stefan Metzmacher --- source3/winbindd/winbindd_cm.c | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 73f431a..08684cc 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -2007,6 +2007,7 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, goto done; } + TALLOC_FREE(conn->samr_pipe); /* * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated @@ -2234,6 +2235,8 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, goto done; } + TALLOC_FREE(conn->lsa_pipe); + if ((conn->cli->user_name[0] == '\0') || (conn->cli->domain[0] == '\0') || (conn->cli->password == NULL || conn->cli->password[0] == '\0')) { @@ -2366,6 +2369,8 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, return NT_STATUS_OK; } + TALLOC_FREE(conn->netlogon_pipe); + result = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_netlogon.syntax_id, &netlogon_pipe); -- 1.6.3.3 From 98180378e08f85e4cc84bbc41e562ced1e349d81 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 25 Mar 2010 15:25:47 +0100 Subject: [PATCH 16/18] s3:winbindd_cm: invalidate connection if cm_connect_netlogon() fails metze (cherry picked from commit 94a4bcd2f0c0464e192556679c6636639cb307ea) (cherry picked from commit c046ae8428fb62ff2749689e7c738f1a2e8f8251) Signed-off-by: Stefan Metzmacher --- source3/winbindd/winbindd_cm.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 08684cc..2ef077d 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -2449,8 +2449,8 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error " "was %s\n", nt_errstr(result))); - /* make sure we return something besides OK */ - return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE; + invalidate_cm_connection(conn); + return result; } /* -- 1.6.3.3 From 68d9b6e3d3ac252ecfc6d627c99ee44267e9443e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 6 Apr 2010 14:45:19 +0200 Subject: [PATCH 17/18] s3:winbindd_reconnect: don't only reconnect on NT_STATUS_UNSUCCESSFUL metze (cherry picked from commit 6bd5a2a3739938f95fce23ab2da652c9b5a48111) (cherry picked from commit 169628fcb656ba5987a99bd50c7f588b731eae51) Signed-off-by: Stefan Metzmacher --- source3/winbindd/winbindd_reconnect.c | 73 ++++++++++++++++++++++++++------ 1 files changed, 59 insertions(+), 14 deletions(-) diff --git a/source3/winbindd/winbindd_reconnect.c b/source3/winbindd/winbindd_reconnect.c index 25debcc..f76a93a 100644 --- a/source3/winbindd/winbindd_reconnect.c +++ b/source3/winbindd/winbindd_reconnect.c @@ -27,6 +27,51 @@ extern struct winbindd_methods msrpc_methods; +static bool reconnect_need_retry(NTSTATUS status) +{ + if (NT_STATUS_IS_OK(status)) { + return false; + } + + if (!NT_STATUS_IS_ERR(status)) { + return false; + } + + if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) { + return false; + } + + if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) { + return false; + } + + if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_GROUP)) { + return false; + } + + if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_ALIAS)) { + return false; + } + + if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_MEMBER)) { + return false; + } + + if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN)) { + return false; + } + + if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_PRIVILEGE)) { + return false; + } + + if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MEMORY)) { + return false; + } + + return true; +} + /* List all users */ static NTSTATUS query_user_list(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, @@ -38,7 +83,7 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain, result = msrpc_methods.query_user_list(domain, mem_ctx, num_entries, info); - if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) + if (reconnect_need_retry(result)) result = msrpc_methods.query_user_list(domain, mem_ctx, num_entries, info); return result; @@ -55,7 +100,7 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain, result = msrpc_methods.enum_dom_groups(domain, mem_ctx, num_entries, info); - if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) + if (reconnect_need_retry(result)) result = msrpc_methods.enum_dom_groups(domain, mem_ctx, num_entries, info); return result; @@ -73,7 +118,7 @@ static NTSTATUS enum_local_groups(struct winbindd_domain *domain, result = msrpc_methods.enum_local_groups(domain, mem_ctx, num_entries, info); - if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) + if (reconnect_need_retry(result)) result = msrpc_methods.enum_local_groups(domain, mem_ctx, num_entries, info); @@ -95,7 +140,7 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain, domain_name, name, sid, type); - if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) + if (reconnect_need_retry(result)) result = msrpc_methods.name_to_sid(domain, mem_ctx, orig_cmd, domain_name, name, sid, type); @@ -118,7 +163,7 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain, result = msrpc_methods.sid_to_name(domain, mem_ctx, sid, domain_name, name, type); - if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) + if (reconnect_need_retry(result)) result = msrpc_methods.sid_to_name(domain, mem_ctx, sid, domain_name, name, type); @@ -139,7 +184,7 @@ static NTSTATUS rids_to_names(struct winbindd_domain *domain, result = msrpc_methods.rids_to_names(domain, mem_ctx, sid, rids, num_rids, domain_name, names, types); - if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) { + if (reconnect_need_retry(result)) { result = msrpc_methods.rids_to_names(domain, mem_ctx, sid, rids, num_rids, domain_name, names, @@ -160,7 +205,7 @@ static NTSTATUS query_user(struct winbindd_domain *domain, result = msrpc_methods.query_user(domain, mem_ctx, user_sid, user_info); - if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) + if (reconnect_need_retry(result)) result = msrpc_methods.query_user(domain, mem_ctx, user_sid, user_info); @@ -179,7 +224,7 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, user_sid, num_groups, user_gids); - if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) + if (reconnect_need_retry(result)) result = msrpc_methods.lookup_usergroups(domain, mem_ctx, user_sid, num_groups, user_gids); @@ -199,7 +244,7 @@ static NTSTATUS lookup_useraliases(struct winbindd_domain *domain, num_aliases, alias_rids); - if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) + if (reconnect_need_retry(result)) result = msrpc_methods.lookup_useraliases(domain, mem_ctx, num_sids, sids, num_aliases, @@ -222,7 +267,7 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, sid_mem, names, name_types); - if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) + if (reconnect_need_retry(result)) result = msrpc_methods.lookup_groupmem(domain, mem_ctx, group_sid, num_names, sid_mem, names, @@ -238,7 +283,7 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq) result = msrpc_methods.sequence_number(domain, seq); - if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) + if (reconnect_need_retry(result)) result = msrpc_methods.sequence_number(domain, seq); return result; @@ -253,7 +298,7 @@ static NTSTATUS lockout_policy(struct winbindd_domain *domain, result = msrpc_methods.lockout_policy(domain, mem_ctx, policy); - if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) + if (reconnect_need_retry(result)) result = msrpc_methods.lockout_policy(domain, mem_ctx, policy); return result; @@ -268,7 +313,7 @@ static NTSTATUS password_policy(struct winbindd_domain *domain, result = msrpc_methods.password_policy(domain, mem_ctx, policy); - if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) + if (reconnect_need_retry(result)) result = msrpc_methods.password_policy(domain, mem_ctx, policy); return result; @@ -288,7 +333,7 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain, num_domains, names, alt_names, dom_sids); - if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) + if (reconnect_need_retry(result)) result = msrpc_methods.trusted_domains(domain, mem_ctx, num_domains, names, alt_names, dom_sids); -- 1.6.3.3 From 9aad33692158b76bb86cfadf9ad8506feece46e2 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 29 Mar 2010 22:03:55 +0200 Subject: [PATCH 18/18] s3:winbindd: correctly retry if the netlogon pipe gets disconnected during a logon call This fixes hopefully the last part of bug #7295. metze (cherry picked from commit 4c6cde99c0751a073120d8bc36d40922d8027344) (cherry picked from commit 482518fcafb18bda1f084ebf1906a2ad02436b80) Signed-off-by: Stefan Metzmacher --- source3/winbindd/winbindd_pam.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 765fb0d..44861df 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1369,7 +1369,7 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain, might not yet have noticed that the DC has killed our connection. */ - if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) { + if (!rpccli_is_connected(netlogon_pipe)) { retry = true; continue; } @@ -1944,7 +1944,7 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, might not yet have noticed that the DC has killed our connection. */ - if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) { + if (!rpccli_is_connected(netlogon_pipe)) { retry = true; continue; } -- 1.6.3.3