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; | 
