From 0089b40a0257ae5e819c0766817c5355f553dc2e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 6 Apr 2010 14:26:29 +0200 Subject: [PATCH] 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 | 34 ++++++---- 6 files changed, 193 insertions(+), 18 deletions(-) diff --git a/source3/include/client.h b/source3/include/client.h index 19142109fd09..bdc6aeb863f0 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 446f0e58bcd0..47b56def86f4 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -5312,6 +5312,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 cc0c66c2171d..94e714d3b817 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 1997e9c8c9d3..ae0c32632412 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 823f216c128a..262caf9ee39e 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 2cc669469024..95e16c381f1f 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,7 +76,7 @@ static struct async_req *rpc_sock_read_send(TALLOC_CTX *mem_ctx, struct rpc_sock_read_state)) { return NULL; } - if (sock_transp->fd == -1) { + if (!rpc_sock_is_connected(sock_transp)) { if (!async_post_ntstatus(result, ev, NT_STATUS_CONNECTION_INVALID)) { goto fail; } @@ -97,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; } @@ -145,7 +159,7 @@ static struct async_req *rpc_sock_write_send(TALLOC_CTX *mem_ctx, struct rpc_sock_write_state)) { return NULL; } - if (sock_transp->fd == -1) { + if (!rpc_sock_is_connected(sock_transp)) { if (!async_post_ntstatus(result, ev, NT_STATUS_CONNECTION_INVALID)) { goto fail; } @@ -183,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; } @@ -235,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; -- 2.34.1