From 8daa83a594a2e98f39d764422bfbdbc62c9efd44 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 19:20:00 +0200 Subject: Adding upstream version 2:4.20.0+dfsg. Signed-off-by: Daniel Baumann --- source3/rpc_client/rpc_transport_np.c | 179 ++++++++++++++++++++++++++++++++++ 1 file changed, 179 insertions(+) create mode 100644 source3/rpc_client/rpc_transport_np.c (limited to 'source3/rpc_client/rpc_transport_np.c') diff --git a/source3/rpc_client/rpc_transport_np.c b/source3/rpc_client/rpc_transport_np.c new file mode 100644 index 0000000..21266c3 --- /dev/null +++ b/source3/rpc_client/rpc_transport_np.c @@ -0,0 +1,179 @@ +/* + * Unix SMB/CIFS implementation. + * RPC client transport over named pipes + * Copyright (C) Volker Lendecke 2009 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "includes.h" +#include "../lib/util/tevent_ntstatus.h" +#include "librpc/rpc/dcerpc_util.h" +#include "rpc_client/rpc_transport.h" +#include "librpc/ndr/ndr_table.h" +#include "libcli/smb/smbXcli_base.h" +#include "libcli/smb/tstream_smbXcli_np.h" +#include "client.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_RPC_CLI + +struct rpc_transport_np_init_state { + struct rpc_cli_transport *transport; + int retries; + struct tevent_context *ev; + struct smbXcli_conn *conn; + int timeout; + struct timeval abs_timeout; + const char *pipe_name; + struct smbXcli_session *session; + struct smbXcli_tcon *tcon; + uint16_t pid; +}; + +static void rpc_transport_np_init_pipe_open(struct tevent_req *subreq); + +struct tevent_req *rpc_transport_np_init_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct cli_state *cli, + const struct ndr_interface_table *table) +{ + struct tevent_req *req; + struct rpc_transport_np_init_state *state; + struct tevent_req *subreq; + + req = tevent_req_create(mem_ctx, &state, + struct rpc_transport_np_init_state); + if (req == NULL) { + return NULL; + } + + if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { + state->tcon = cli->smb2.tcon; + state->session = cli->smb2.session; + } else { + state->tcon = cli->smb1.tcon; + state->session = cli->smb1.session; + state->pid = cli->smb1.pid; + } + + state->ev = ev; + state->conn = cli->conn; + state->timeout = cli->timeout; + state->abs_timeout = timeval_current_ofs_msec(cli->timeout); + state->pipe_name = dcerpc_default_transport_endpoint(state, NCACN_NP, + table); + if (tevent_req_nomem(state->pipe_name, req)) { + return tevent_req_post(req, ev); + } + + while (state->pipe_name[0] == '\\') { + state->pipe_name++; + } + + subreq = tstream_smbXcli_np_open_send(state, ev, state->conn, + state->session, state->tcon, + state->pid, state->timeout, + state->pipe_name); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, rpc_transport_np_init_pipe_open, req); + + return req; +} + +static void rpc_transport_np_init_pipe_open_retry(struct tevent_context *ev, + struct tevent_timer *te, + struct timeval t, + void *priv_data) +{ + struct tevent_req *subreq; + struct tevent_req *req = talloc_get_type(priv_data, struct tevent_req); + struct rpc_transport_np_init_state *state = tevent_req_data( + req, struct rpc_transport_np_init_state); + + subreq = tstream_smbXcli_np_open_send(state, ev, + state->conn, + state->session, + state->tcon, + state->pid, + state->timeout, + state->pipe_name); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, rpc_transport_np_init_pipe_open, req); + state->retries++; +} + +static void rpc_transport_np_init_pipe_open(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct rpc_transport_np_init_state *state = tevent_req_data( + req, struct rpc_transport_np_init_state); + NTSTATUS status; + struct tstream_context *stream; + + status = tstream_smbXcli_np_open_recv(subreq, state, &stream); + TALLOC_FREE(subreq); + if (NT_STATUS_EQUAL(status, NT_STATUS_PIPE_NOT_AVAILABLE) + && (!timeval_expired(&state->abs_timeout))) { + struct tevent_timer *te; + /* + * Retry on STATUS_PIPE_NOT_AVAILABLE, Windows starts some + * servers (FssagentRpc) on demand. + */ + DEBUG(2, ("RPC pipe %s not available, retry %d\n", + state->pipe_name, state->retries)); + te = tevent_add_timer(state->ev, state, + timeval_current_ofs_msec(100 * state->retries), + rpc_transport_np_init_pipe_open_retry, req); + if (tevent_req_nomem(te, req)) { + DEBUG(2, ("Failed to create asynchronous " + "tevent_timer\n")); + } + return; + } + + if (tevent_req_nterror(req, status)) { + return; + } + + status = rpc_transport_tstream_init(state, + &stream, + &state->transport); + if (tevent_req_nterror(req, status)) { + return; + } + + tevent_req_done(req); +} + +NTSTATUS rpc_transport_np_init_recv(struct tevent_req *req, + TALLOC_CTX *mem_ctx, + struct rpc_cli_transport **presult) +{ + struct rpc_transport_np_init_state *state = tevent_req_data( + req, struct rpc_transport_np_init_state); + NTSTATUS status; + + if (tevent_req_is_nterror(req, &status)) { + return status; + } + + *presult = talloc_move(mem_ctx, &state->transport); + return NT_STATUS_OK; +} -- cgit v1.2.3