diff options
-rw-r--r-- | source3/include/client.h | 3 | ||||
-rw-r--r-- | source3/include/proto.h | 1 | ||||
-rw-r--r-- | source3/rpc_client/cli_pipe.c | 13 | ||||
-rw-r--r-- | source3/rpc_client/rpc_transport_np.c | 66 | ||||
-rw-r--r-- | source3/rpc_client/rpc_transport_smbd.c | 76 | ||||
-rw-r--r-- | source3/rpc_client/rpc_transport_sock.c | 34 |
6 files changed, 175 insertions, 18 deletions
diff --git a/source3/include/client.h b/source3/include/client.h index 72cea4a82c..c8b90634d4 100644 --- a/source3/include/client.h +++ b/source3/include/client.h @@ -110,6 +110,9 @@ struct rpc_cli_transport { */ NTSTATUS (*trans_recv)(struct tevent_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 96ca32e228..a70707b809 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -5291,6 +5291,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 09874c72cd..551516bb5b 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -3093,6 +3093,19 @@ unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli, return 0; } +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 96a8988e64..ab67fc550e 100644 --- a/source3/rpc_client/rpc_transport_np.c +++ b/source3/rpc_client/rpc_transport_np.c @@ -28,9 +28,28 @@ 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) { - 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; } @@ -49,6 +68,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; }; @@ -64,13 +84,23 @@ static struct tevent_req *rpc_np_write_send(TALLOC_CTX *mem_ctx, priv, struct rpc_transport_np_state); struct tevent_req *req, *subreq; struct rpc_np_write_state *state; + bool ok; req = tevent_req_create(mem_ctx, &state, struct rpc_np_write_state); if (req == NULL) { return NULL; } + + ok = rpc_np_is_connected(np_transport); + if (!ok) { + tevent_req_nterror(req, NT_STATUS_CONNECTION_INVALID); + return tevent_req_post(req, ev); + } + + 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. */ @@ -93,6 +123,7 @@ static void rpc_np_write_done(struct tevent_req *subreq) status = cli_write_andx_recv(subreq, &state->written); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { + state->np_transport->cli = NULL; tevent_req_nterror(req, status); return; } @@ -113,6 +144,7 @@ static NTSTATUS rpc_np_write_recv(struct tevent_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; @@ -129,11 +161,20 @@ static struct tevent_req *rpc_np_read_send(TALLOC_CTX *mem_ctx, priv, struct rpc_transport_np_state); struct tevent_req *req, *subreq; struct rpc_np_read_state *state; + bool ok; req = tevent_req_create(mem_ctx, &state, struct rpc_np_read_state); if (req == NULL) { return NULL; } + + ok = rpc_np_is_connected(np_transport); + if (!ok) { + tevent_req_nterror(req, NT_STATUS_CONNECTION_INVALID); + return tevent_req_post(req, ev); + } + + state->np_transport = np_transport; state->data = data; state->size = size; @@ -171,18 +212,21 @@ static void rpc_np_read_done(struct tevent_req *subreq) } if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(subreq); + state->np_transport->cli = NULL; tevent_req_nterror(req, status); return; } if (state->received > state->size) { TALLOC_FREE(subreq); + state->np_transport->cli = NULL; tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); return; } if (state->received == 0) { TALLOC_FREE(subreq); + state->np_transport->cli = NULL; tevent_req_nterror(req, NT_STATUS_PIPE_BROKEN); return; } @@ -206,6 +250,7 @@ static NTSTATUS rpc_np_read_recv(struct tevent_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; @@ -224,12 +269,20 @@ static struct tevent_req *rpc_np_trans_send(TALLOC_CTX *mem_ctx, priv, struct rpc_transport_np_state); struct tevent_req *req, *subreq; struct rpc_np_trans_state *state; + bool ok; req = tevent_req_create(mem_ctx, &state, struct rpc_np_trans_state); if (req == NULL) { return NULL; } + ok = rpc_np_is_connected(np_transport); + if (!ok) { + tevent_req_nterror(req, NT_STATUS_CONNECTION_INVALID); + return tevent_req_post(req, ev); + } + + state->np_transport = np_transport; state->max_rdata_len = max_rdata_len; SSVAL(state->setup+0, 0, TRANSACT_DCERPCCMD); @@ -265,16 +318,19 @@ static void rpc_np_trans_done(struct tevent_req *subreq) status = NT_STATUS_OK; } if (!NT_STATUS_IS_OK(status)) { + state->np_transport->cli = NULL; tevent_req_nterror(req, status); return; } if (state->rdata_len > state->max_rdata_len) { + state->np_transport->cli = NULL; tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); return; } if (state->rdata_len == 0) { + state->np_transport->cli = NULL; tevent_req_nterror(req, NT_STATUS_PIPE_BROKEN); return; } @@ -311,6 +367,7 @@ struct tevent_req *rpc_transport_np_init_send(TALLOC_CTX *mem_ctx, { struct tevent_req *req, *subreq; struct rpc_transport_np_init_state *state; + bool ok; req = tevent_req_create(mem_ctx, &state, struct rpc_transport_np_init_state); @@ -318,6 +375,12 @@ struct tevent_req *rpc_transport_np_init_send(TALLOC_CTX *mem_ctx, return NULL; } + ok = cli_state_is_connected(cli); + if (!ok) { + tevent_req_nterror(req, NT_STATUS_CONNECTION_INVALID); + return tevent_req_post(req, ev); + } + state->transport = talloc(state, struct rpc_cli_transport); if (tevent_req_nomem(state->transport, req)) { return tevent_req_post(req, ev); @@ -383,6 +446,7 @@ NTSTATUS rpc_transport_np_init_recv(struct tevent_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 929e553c84..47c426f120 100644 --- a/source3/rpc_client/rpc_transport_smbd.c +++ b/source3/rpc_client/rpc_transport_smbd.c @@ -419,8 +419,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; }; @@ -435,12 +480,20 @@ static struct tevent_req *rpc_smbd_write_send(TALLOC_CTX *mem_ctx, priv, struct rpc_transport_smbd_state); struct tevent_req *req, *subreq; struct rpc_smbd_write_state *state; + bool ok; req = tevent_req_create(mem_ctx, &state, struct rpc_smbd_write_state); if (req == NULL) { return NULL; } - state->sub_transp = transp->sub_transp; + + ok = rpc_smbd_is_connected(transp); + if (!ok) { + tevent_req_nterror(req, NT_STATUS_CONNECTION_INVALID); + return tevent_req_post(req, ev); + } + + state->transp = transp; subreq = transp->sub_transp->write_send(state, ev, data, size, transp->sub_transp->priv); @@ -468,9 +521,10 @@ static void rpc_smbd_write_done(struct tevent_req *subreq) req, 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); tevent_req_nterror(req, status); return; } @@ -491,7 +545,7 @@ static NTSTATUS rpc_smbd_write_recv(struct tevent_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; }; @@ -506,12 +560,20 @@ static struct tevent_req *rpc_smbd_read_send(TALLOC_CTX *mem_ctx, priv, struct rpc_transport_smbd_state); struct tevent_req *req, *subreq; struct rpc_smbd_read_state *state; + bool ok; req = tevent_req_create(mem_ctx, &state, struct rpc_smbd_read_state); if (req == NULL) { return NULL; } - state->sub_transp = transp->sub_transp; + + ok = rpc_smbd_is_connected(transp); + if (!ok) { + tevent_req_nterror(req, NT_STATUS_CONNECTION_INVALID); + return tevent_req_post(req, ev); + } + + state->transp = transp; subreq = transp->sub_transp->read_send(state, ev, data, size, transp->sub_transp->priv); @@ -538,9 +600,10 @@ static void rpc_smbd_read_done(struct tevent_req *subreq) req, 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); tevent_req_nterror(req, status); return; } @@ -645,6 +708,7 @@ NTSTATUS rpc_transport_smbd_init_recv(struct tevent_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 4ab17dbd8d..5132504a85 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; @@ -58,7 +75,7 @@ static struct tevent_req *rpc_sock_read_send(TALLOC_CTX *mem_ctx, if (req == NULL) { return NULL; } - if (sock_transp->fd == -1) { + if (!rpc_sock_is_connected(sock_transp)) { tevent_req_nterror(req, NT_STATUS_CONNECTION_INVALID); return tevent_req_post(req, ev); } @@ -94,11 +111,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); tevent_req_nterror(req, map_nt_error_from_unix(err)); return; } @@ -141,7 +155,7 @@ static struct tevent_req *rpc_sock_write_send(TALLOC_CTX *mem_ctx, if (req == NULL) { return NULL; } - if (sock_transp->fd == -1) { + if (!rpc_sock_is_connected(sock_transp)) { tevent_req_nterror(req, NT_STATUS_CONNECTION_INVALID); return tevent_req_post(req, ev); } @@ -177,11 +191,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); tevent_req_nterror(req, map_nt_error_from_unix(err)); return; } @@ -229,6 +240,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; |