util:datablob: data_blob_pad checks its alignment assumption
[samba.git] / source3 / rpc_client / local_np.c
blob10c6434e397c1ce101b81d01f4d7840e2ca90db2
1 /*
2 * Unix SMB/CIFS implementation.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
18 #include "source3/include/includes.h"
19 #include <spawn.h>
20 #include "local_np.h"
21 #include "lib/async_req/async_sock.h"
22 #include "librpc/gen_ndr/ndr_named_pipe_auth.h"
23 #include "libcli/named_pipe_auth/npa_tstream.h"
24 #include "libcli/named_pipe_auth/tstream_u32_read.h"
25 #include "lib/util/tevent_unix.h"
26 #include "auth/auth_util.h"
27 #include "libcli/security/dom_sid.h"
28 #include "libcli/security/security_token.h"
29 #include "nsswitch/winbind_client.h"
31 /**
32 * @file local_np.c
34 * Connect to a local named pipe by connecting to
35 * samba-dcerpcd. Start samba-dcerpcd if it isn't
36 * already running.
39 extern bool override_logfile;
41 struct np_sock_connect_state {
42 struct tevent_context *ev;
43 struct samba_sockaddr addr;
44 const struct named_pipe_auth_req *npa_req;
45 struct named_pipe_auth_rep *npa_rep;
47 DATA_BLOB npa_blob;
48 struct iovec iov;
50 int sock;
51 struct tevent_req *subreq;
52 struct tstream_context *transport;
53 struct tstream_context *npa_stream;
56 static void np_sock_connect_cleanup(
57 struct tevent_req *req, enum tevent_req_state req_state);
58 static void np_sock_connect_before(void *private_data);
59 static void np_sock_connect_after(void *private_data);
60 static void np_sock_connect_connected(struct tevent_req *subreq);
61 static void np_sock_connect_written(struct tevent_req *subreq);
62 static void np_sock_connect_read_done(struct tevent_req *subreq);
64 static struct tevent_req *np_sock_connect_send(
65 TALLOC_CTX *mem_ctx,
66 struct tevent_context *ev,
67 const char *sockpath,
68 const struct named_pipe_auth_req *npa_req)
70 struct tevent_req *req = NULL;
71 struct np_sock_connect_state *state = NULL;
72 size_t len;
73 int ret;
74 bool ok;
76 req = tevent_req_create(mem_ctx, &state, struct np_sock_connect_state);
77 if (req == NULL) {
78 return NULL;
80 state->ev = ev;
81 state->npa_req = npa_req;
82 state->sock = -1;
83 state->addr.u.un.sun_family = AF_UNIX;
85 state->npa_rep = talloc_zero(state, struct named_pipe_auth_rep);
86 if (tevent_req_nomem(state->npa_rep, req)) {
87 return tevent_req_post(req, ev);
90 tevent_req_set_cleanup_fn(req, np_sock_connect_cleanup);
92 state->addr.sa_socklen = sizeof(struct sockaddr_un);
93 len = strlcpy(state->addr.u.un.sun_path,
94 sockpath,
95 sizeof(state->addr.u.un.sun_path));
96 if (len >= sizeof(state->addr.u.un.sun_path)) {
97 tevent_req_error(req, ENAMETOOLONG);
98 return tevent_req_post(req, ev);
101 state->sock = socket(AF_UNIX, SOCK_STREAM, 0);
102 if (state->sock == -1) {
103 tevent_req_error(req, errno);
104 return tevent_req_post(req, ev);
107 ret = set_blocking(state->sock, true);
108 if (ret == -1) {
109 tevent_req_error(req, errno);
110 return tevent_req_post(req, ev);
112 ok = set_close_on_exec(state->sock);
113 if (!ok) {
114 tevent_req_error(req, errno);
115 return tevent_req_post(req, ev);
118 state->subreq = async_connect_send(
119 state,
121 state->sock,
122 &state->addr.u.sa,
123 state->addr.sa_socklen,
124 np_sock_connect_before,
125 np_sock_connect_after,
126 NULL);
127 if (tevent_req_nomem(state->subreq, req)) {
128 return tevent_req_post(req, ev);
130 tevent_req_set_callback(state->subreq, np_sock_connect_connected, req);
132 return req;
135 static void np_sock_connect_cleanup(
136 struct tevent_req *req, enum tevent_req_state req_state)
138 struct np_sock_connect_state *state = tevent_req_data(
139 req, struct np_sock_connect_state);
141 TALLOC_FREE(state->subreq);
142 TALLOC_FREE(state->transport);
144 if (state->sock != -1) {
145 close(state->sock);
146 state->sock = -1;
150 static void np_sock_connect_before(void *private_data)
152 become_root();
155 static void np_sock_connect_after(void *private_data)
157 unbecome_root();
160 static void np_sock_connect_connected(struct tevent_req *subreq)
162 struct tevent_req *req = tevent_req_callback_data(
163 subreq, struct tevent_req);
164 struct np_sock_connect_state *state = tevent_req_data(
165 req, struct np_sock_connect_state);
166 enum ndr_err_code ndr_err;
167 int ret, err;
169 SMB_ASSERT(subreq == state->subreq);
171 ret = async_connect_recv(subreq, &err);
172 TALLOC_FREE(subreq);
173 state->subreq = NULL;
174 if (ret == -1) {
175 DBG_DEBUG("async_connect_recv returned %s\n", strerror(err));
176 tevent_req_error(req, err);
177 return;
181 * As a quick workaround for bug 15310 we have done the
182 * connect in blocking mode (see np_sock_connect_send()). The
183 * rest of our code expects a nonblocking socket, activate
184 * this after the connect succeeded.
186 ret = set_blocking(state->sock, false);
187 if (ret == -1) {
188 tevent_req_error(req, errno);
189 return;
192 ret = tstream_bsd_existing_socket(
193 state, state->sock, &state->transport);
194 if (ret == -1) {
195 err = errno;
196 DBG_DEBUG("tstream_bsd_existing_socket failed: %s\n",
197 strerror(err));
198 tevent_req_error(req, err);
199 return;
201 state->sock = -1;
203 ndr_err = ndr_push_struct_blob(
204 &state->npa_blob,
205 state,
206 state->npa_req,
207 (ndr_push_flags_fn_t)ndr_push_named_pipe_auth_req);
208 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
209 DBG_DEBUG("ndr_push_struct_blob failed: %s\n",
210 ndr_errstr(ndr_err));
211 tevent_req_error(req, ndr_map_error2errno(ndr_err));
212 return;
214 state->iov = (struct iovec) {
215 .iov_base = state->npa_blob.data,
216 .iov_len = state->npa_blob.length,
219 subreq = tstream_writev_send(
220 state, state->ev, state->transport, &state->iov, 1);
221 if (tevent_req_nomem(subreq, req)) {
222 return;
224 tevent_req_set_callback(subreq, np_sock_connect_written, req);
227 static void np_sock_connect_written(struct tevent_req *subreq)
229 struct tevent_req *req = tevent_req_callback_data(
230 subreq, struct tevent_req);
231 struct np_sock_connect_state *state = tevent_req_data(
232 req, struct np_sock_connect_state);
233 int ret, err;
235 ret = tstream_writev_recv(subreq, &err);
236 TALLOC_FREE(subreq);
237 if (ret == -1) {
238 DBG_DEBUG("tstream_writev_recv returned %s\n", strerror(err));
239 tevent_req_error(req, err);
240 return;
243 subreq = tstream_u32_read_send(
244 state, state->ev, 0x00FFFFFF, state->transport);
245 if (tevent_req_nomem(subreq, req)) {
246 return;
248 tevent_req_set_callback(subreq, np_sock_connect_read_done, req);
251 static void np_sock_connect_read_done(struct tevent_req *subreq)
253 struct tevent_req *req = tevent_req_callback_data(
254 subreq, struct tevent_req);
255 struct np_sock_connect_state *state = tevent_req_data(
256 req, struct np_sock_connect_state);
257 DATA_BLOB in;
258 int ret;
259 enum ndr_err_code ndr_err;
261 ret = tstream_u32_read_recv(subreq, state, &in.data, &in.length);
262 TALLOC_FREE(subreq);
263 if (tevent_req_error(req, ret)) {
264 return;
267 ndr_err = ndr_pull_struct_blob_all(
268 &in,
269 state->npa_rep,
270 state->npa_rep,
271 (ndr_pull_flags_fn_t)ndr_pull_named_pipe_auth_rep);
272 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
273 DBG_DEBUG("ndr_pull_named_pipe_auth_rep failed: %s\n",
274 ndr_errstr(ndr_err));
275 tevent_req_error(req, ndr_map_error2errno(ndr_err));
276 return;
278 if (state->npa_rep->level != 8) {
279 DBG_DEBUG("npa level = %" PRIu32 ", expected 8\n",
280 state->npa_rep->level);
281 tevent_req_error(req, EIO);
282 return;
285 ret = tstream_npa_existing_stream(state,
286 &state->transport,
287 state->npa_rep->info.info8.file_type,
288 &state->npa_stream);
289 if (ret == -1) {
290 ret = errno;
291 DBG_DEBUG("tstream_npa_existing_stream failed: %s\n",
292 strerror(ret));
293 tevent_req_error(req, ret);
294 return;
297 tevent_req_done(req);
300 static int np_sock_connect_recv(
301 struct tevent_req *req,
302 TALLOC_CTX *mem_ctx,
303 struct tstream_context **stream)
305 struct np_sock_connect_state *state = tevent_req_data(
306 req, struct np_sock_connect_state);
307 int err;
309 if (tevent_req_is_unix_error(req, &err)) {
310 tevent_req_received(req);
311 return err;
313 *stream = talloc_move(mem_ctx, &state->npa_stream);
314 tevent_req_received(req);
315 return 0;
318 struct start_rpc_host_state {
319 int ready_fd;
320 struct tevent_req *read_ready_req;
323 static void start_rpc_host_cleanup(
324 struct tevent_req *req, enum tevent_req_state req_state);
325 static void start_rpc_host_ready(struct tevent_req *subreq);
328 * Start samba-dcerpcd and wait for it to report ready.
330 static struct tevent_req *start_rpc_host_send(
331 TALLOC_CTX *mem_ctx, struct tevent_context *ev)
333 struct tevent_req *req = NULL, *subreq = NULL;
334 struct start_rpc_host_state *state = NULL;
335 int ret;
336 int ready_fds[2] = { -1, -1 };
337 char **argv = NULL;
338 pid_t pid;
339 bool ok;
341 req = tevent_req_create(
342 mem_ctx, &state, struct start_rpc_host_state);
343 if (req == NULL) {
344 return NULL;
347 ret = pipe(ready_fds);
348 if (ret == -1) {
349 ret = errno;
350 DBG_DEBUG("pipe() failed: %s\n", strerror(ret));
351 goto fail;
354 ok = smb_set_close_on_exec(ready_fds[0]);
355 if (!ok) {
356 ret = errno;
357 DBG_DEBUG("smb_set_close_on_exec failed: %s\n",
358 strerror(ret));
359 goto fail;
362 argv = str_list_make_empty(mem_ctx);
363 str_list_add_printf(
364 &argv, "%s/samba-dcerpcd", get_dyn_SAMBA_LIBEXECDIR());
365 if (!is_default_dyn_CONFIGFILE()) {
366 str_list_add_printf(
367 &argv, "--configfile=%s", get_dyn_CONFIGFILE());
369 str_list_add_printf(&argv, "--libexec-rpcds");
370 str_list_add_printf(&argv, "--ready-signal-fd=%d", ready_fds[1]);
371 str_list_add_printf(&argv, "--np-helper");
372 str_list_add_printf(
373 &argv, "--debuglevel=%d", debuglevel_get_class(DBGC_RPC_SRV));
374 if (!is_default_dyn_LOGFILEBASE()) {
375 str_list_add_printf(
376 &argv, "--log-basename=%s", get_dyn_LOGFILEBASE());
378 if (argv == NULL) {
379 errno = ENOMEM;
380 goto fail;
383 become_root();
384 ret = posix_spawn(&pid, argv[0], NULL, NULL, argv, environ);
385 unbecome_root();
386 if (ret != 0) {
387 DBG_DEBUG("posix_spawn() failed: %s\n", strerror(ret));
388 goto fail;
391 state->ready_fd = ready_fds[0];
392 ready_fds[0] = -1;
393 tevent_req_set_cleanup_fn(req, start_rpc_host_cleanup);
395 close(ready_fds[1]);
396 ready_fds[1] = -1;
398 subreq = read_packet_send(state, ev, state->ready_fd, 1, NULL, NULL);
399 if (tevent_req_nomem(subreq, req)) {
400 return tevent_req_post(req, ev);
402 tevent_req_set_callback(subreq, start_rpc_host_ready, req);
403 return req;
405 fail:
406 if (ready_fds[0] != -1) {
407 close(ready_fds[0]);
408 ready_fds[0] = -1;
410 if (ready_fds[1] != -1) {
411 close(ready_fds[1]);
412 ready_fds[1] = -1;
414 tevent_req_error(req, ret);
415 return tevent_req_post(req, ev);
418 static void start_rpc_host_cleanup(
419 struct tevent_req *req, enum tevent_req_state req_state)
421 struct start_rpc_host_state *state = tevent_req_data(
422 req, struct start_rpc_host_state);
424 if (state->ready_fd != -1) {
425 close(state->ready_fd);
426 state->ready_fd = -1;
430 static void start_rpc_host_ready(struct tevent_req *subreq)
432 struct tevent_req *req = tevent_req_callback_data(
433 subreq, struct tevent_req);
434 struct start_rpc_host_state *state = tevent_req_data(
435 req, struct start_rpc_host_state);
436 uint8_t *buf;
437 int err;
438 ssize_t nread;
440 nread = read_packet_recv(subreq, state, &buf, &err);
441 TALLOC_FREE(subreq);
442 if (nread == -1) {
443 tevent_req_error(req, err);
444 return;
447 close(state->ready_fd);
448 state->ready_fd = -1;
450 tevent_req_done(req);
453 static int start_rpc_host_recv(struct tevent_req *req)
455 return tevent_req_simple_recv_unix(req);
458 struct local_np_connect_state {
459 struct tevent_context *ev;
460 const char *socketpath;
461 struct named_pipe_auth_req *npa_req;
462 struct tstream_context *npa_stream;
465 static void local_np_connect_connected(struct tevent_req *subreq);
466 static void local_np_connect_started(struct tevent_req *subreq);
467 static void local_np_connect_retried(struct tevent_req *subreq);
470 * @brief Async connect to a local named pipe RPC interface
472 * Start "samba-dcerpcd" on demand if it does not exist
474 * @param[in] mem_ctx The memory context to use.
475 * @param[in] ev The tevent context to use.
477 * @param[in] pipename The raw pipename to connect to without path
478 * @param[in] remote_client_name The client name to transmit
479 * @param[in] remote_client_addr The client addr to transmit
480 * @param[in] local_server_name The server name to transmit
481 * @param[in] local_server_addr The server addr to transmit
482 * @param[in] session_info The authorization info to use
483 * @param[in] need_idle_server Does this need to be an exclusive server?
484 * @return The tevent_req that was started
487 struct tevent_req *local_np_connect_send(
488 TALLOC_CTX *mem_ctx,
489 struct tevent_context *ev,
490 const char *pipename,
491 enum dcerpc_transport_t transport,
492 const char *remote_client_name,
493 const struct tsocket_address *remote_client_addr,
494 const char *local_server_name,
495 const struct tsocket_address *local_server_addr,
496 const struct auth_session_info *session_info,
497 bool need_idle_server)
499 struct tevent_req *req = NULL, *subreq = NULL;
500 struct local_np_connect_state *state = NULL;
501 struct named_pipe_auth_req_info8 *i8 = NULL;
502 const char *socket_dir = NULL;
503 char *lower_case_pipename = NULL;
504 struct dom_sid npa_sid = global_sid_Samba_NPA_Flags;
505 uint32_t npa_flags = 0;
506 struct security_token *token = NULL;
507 NTSTATUS status;
508 size_t num_npa_sids;
509 bool ok;
511 req = tevent_req_create(
512 mem_ctx, &state, struct local_np_connect_state);
513 if (req == NULL) {
514 return NULL;
516 state->ev = ev;
518 num_npa_sids =
519 security_token_count_flag_sids(session_info->security_token,
520 &npa_sid,
522 NULL);
523 if (num_npa_sids != 0) {
524 DBG_ERR("ERROR: %zu NPA Flags SIDs have already been "
525 "detected in the security token!\n",
526 num_npa_sids);
527 tevent_req_error(req, EACCES);
528 return tevent_req_post(req, ev);
531 socket_dir = lp_parm_const_string(
532 GLOBAL_SECTION_SNUM, "external_rpc_pipe", "socket_dir",
533 lp_ncalrpc_dir());
534 if (socket_dir == NULL) {
535 DBG_DEBUG("external_rpc_pipe:socket_dir not set\n");
536 tevent_req_error(req, EINVAL);
537 return tevent_req_post(req, ev);
540 lower_case_pipename = strlower_talloc(state, pipename);
541 if (tevent_req_nomem(lower_case_pipename, req)) {
542 return tevent_req_post(req, ev);
546 * Ensure we cannot process a path that exits
547 * the socket_dir.
549 if (ISDOTDOT(lower_case_pipename) ||
550 (strchr(lower_case_pipename, '/')!=NULL))
552 DBG_DEBUG("attempt to connect to invalid pipe pathname %s\n",
553 lower_case_pipename);
554 tevent_req_error(req, ENOENT);
555 return tevent_req_post(req, ev);
558 state->socketpath = talloc_asprintf(
559 state, "%s/np/%s", socket_dir, lower_case_pipename);
560 if (tevent_req_nomem(state->socketpath, req)) {
561 return tevent_req_post(req, ev);
563 TALLOC_FREE(lower_case_pipename);
565 state->npa_req = talloc_zero(state, struct named_pipe_auth_req);
566 if (tevent_req_nomem(state->npa_req, req)) {
567 return tevent_req_post(req, ev);
569 state->npa_req->level = 8;
571 i8 = &state->npa_req->info.info8;
573 i8->transport = transport;
575 /* we don't have "int" in IDL, make sure we don't overflow */
576 SMB_ASSERT(i8->transport == transport);
578 if (remote_client_name == NULL) {
579 remote_client_name = get_myname(state->npa_req);
580 if (remote_client_name == NULL) {
581 tevent_req_error(req, errno);
582 return tevent_req_post(req, ev);
585 i8->remote_client_name = remote_client_name;
587 if (remote_client_addr == NULL) {
588 struct tsocket_address *addr = NULL;
589 int ret = tsocket_address_inet_from_strings(
590 state->npa_req, "ip", NULL, 0, &addr);
591 if (ret != 0) {
592 tevent_req_error(req, errno);
593 return tevent_req_post(req, ev);
595 remote_client_addr = addr;
597 i8->remote_client_addr =
598 tsocket_address_inet_addr_string(remote_client_addr,
599 state->npa_req);
600 if (i8->remote_client_addr == NULL) {
601 tevent_req_error(req, errno);
602 return tevent_req_post(req, ev);
604 i8->remote_client_port = tsocket_address_inet_port(remote_client_addr);
606 if (local_server_name == NULL) {
607 local_server_name = remote_client_name;
609 i8->local_server_name = local_server_name;
611 if (local_server_addr == NULL) {
612 struct tsocket_address *addr = NULL;
613 int ret = tsocket_address_inet_from_strings(
614 state->npa_req, "ip", NULL, 0, &addr);
615 if (ret != 0) {
616 tevent_req_error(req, errno);
617 return tevent_req_post(req, ev);
619 local_server_addr = addr;
621 i8->local_server_addr =
622 tsocket_address_inet_addr_string(local_server_addr,
623 state->npa_req);
624 if (i8->local_server_addr == NULL) {
625 tevent_req_error(req, errno);
626 return tevent_req_post(req, ev);
628 i8->local_server_port = tsocket_address_inet_port(local_server_addr);
630 i8->session_info = talloc_zero(state->npa_req,
631 struct auth_session_info_transport);
632 if (tevent_req_nomem(i8->session_info, req)) {
633 return tevent_req_post(req, ev);
636 i8->session_info->session_info =
637 copy_session_info(i8->session_info, session_info);
638 if (tevent_req_nomem(i8->session_info->session_info, req)) {
639 return tevent_req_post(req, ev);
642 if (need_idle_server) {
643 npa_flags |= SAMBA_NPA_FLAGS_NEED_IDLE;
646 ok = winbind_env_set();
647 if (ok) {
648 npa_flags |= SAMBA_NPA_FLAGS_WINBIND_OFF;
651 ok = sid_append_rid(&npa_sid, npa_flags);
652 if (!ok) {
653 tevent_req_error(req, EINVAL);
654 return tevent_req_post(req, ev);
657 token = i8->session_info->session_info->security_token;
659 status = add_sid_to_array_unique(token,
660 &npa_sid,
661 &token->sids,
662 &token->num_sids);
663 if (!NT_STATUS_IS_OK(status)) {
664 tevent_req_oom(req);
665 return tevent_req_post(req, ev);
668 subreq = np_sock_connect_send(
669 state, state->ev, state->socketpath, state->npa_req);
670 if (tevent_req_nomem(subreq, req)) {
671 return tevent_req_post(req, ev);
673 tevent_req_set_callback(subreq, local_np_connect_connected, req);
675 return req;
678 static void local_np_connect_connected(struct tevent_req *subreq)
680 struct tevent_req *req = tevent_req_callback_data(
681 subreq, struct tevent_req);
682 struct local_np_connect_state *state = tevent_req_data(
683 req, struct local_np_connect_state);
684 int ret;
686 ret = np_sock_connect_recv(subreq, state, &state->npa_stream);
687 TALLOC_FREE(subreq);
689 if (ret == 0) {
690 tevent_req_done(req);
691 return;
694 DBG_DEBUG("np_sock_connect failed: %s\n", strerror(ret));
696 if (!lp_rpc_start_on_demand_helpers()) {
698 * samba-dcerpcd should already be started in
699 * daemon/standalone mode when "rpc start on demand
700 * helpers = false". We are prohibited from starting
701 * on demand as a named-pipe helper.
703 DBG_ERR("Can't connect to a running samba-dcerpcd. smb.conf "
704 "config prohibits starting as named pipe helper as "
705 "the [global] section contains "
706 "\"rpc start on demand helpers = false\".\n");
707 tevent_req_error(req, ret);
708 return;
712 * samba-dcerpcd isn't running. We need to start it.
713 * Note if it doesn't start we treat this as a fatal
714 * error for connecting to the named pipe and don't
715 * keep trying to restart for this connection.
717 subreq = start_rpc_host_send(state, state->ev);
718 if (tevent_req_nomem(subreq, req)) {
719 return;
721 tevent_req_set_callback(subreq, local_np_connect_started, req);
724 static void local_np_connect_started(struct tevent_req *subreq)
726 struct tevent_req *req = tevent_req_callback_data(
727 subreq, struct tevent_req);
728 struct local_np_connect_state *state = tevent_req_data(
729 req, struct local_np_connect_state);
730 int ret;
732 ret = start_rpc_host_recv(subreq);
733 TALLOC_FREE(subreq);
734 if (tevent_req_error(req, ret)) {
735 DBG_DEBUG("start_rpc_host_recv failed: %s\n",
736 strerror(ret));
737 return;
740 subreq = np_sock_connect_send(
741 state, state->ev, state->socketpath, state->npa_req);
742 if (tevent_req_nomem(subreq, req)) {
743 return;
745 tevent_req_set_callback(subreq, local_np_connect_retried, req);
748 static void local_np_connect_retried(struct tevent_req *subreq)
750 struct tevent_req *req = tevent_req_callback_data(
751 subreq, struct tevent_req);
752 struct local_np_connect_state *state = tevent_req_data(
753 req, struct local_np_connect_state);
754 int ret;
756 ret = np_sock_connect_recv(subreq, state, &state->npa_stream);
757 TALLOC_FREE(subreq);
758 if (tevent_req_error(req, ret)) {
759 return;
761 tevent_req_done(req);
765 * @brief Receive handle to a local named pipe RPC interface
767 * @param[in] req The tevent_req that started the operation
768 * @param[in] ev The tevent context to use.
769 * @param[in] mem_ctx The memory context to put pstream on
770 * @param[out] pstream The established connection to the RPC server
772 * @return 0/errno
775 int local_np_connect_recv(
776 struct tevent_req *req,
777 TALLOC_CTX *mem_ctx,
778 struct tstream_context **pstream)
780 struct local_np_connect_state *state = tevent_req_data(
781 req, struct local_np_connect_state);
782 int err;
784 if (tevent_req_is_unix_error(req, &err)) {
785 tevent_req_received(req);
786 return err;
789 *pstream = talloc_move(mem_ctx, &state->npa_stream);
790 return 0;
794 * @brief Sync connect to a local named pipe RPC interface
796 * Start "samba-dcerpcd" on demand if it does not exist
798 * @param[in] pipename The raw pipename to connect to without path
799 * @param[in] remote_client_name The client name to transmit
800 * @param[in] remote_client_addr The client addr to transmit
801 * @param[in] local_server_name The server name to transmit
802 * @param[in] local_server_addr The server addr to transmit
803 * @param[in] session_info The authorization info to use
804 * @param[in] need_idle_server Does this need to be an exclusive server?
805 * @param[in] mem_ctx The memory context to use.
806 * @param[out] pstream The established connection to the RPC server
807 * @return 0/errno
810 int local_np_connect(
811 const char *pipename,
812 enum dcerpc_transport_t transport,
813 const char *remote_client_name,
814 const struct tsocket_address *remote_client_addr,
815 const char *local_server_name,
816 const struct tsocket_address *local_server_addr,
817 const struct auth_session_info *session_info,
818 bool need_idle_server,
819 TALLOC_CTX *mem_ctx,
820 struct tstream_context **pstream)
822 struct tevent_context *ev = NULL;
823 struct tevent_req *req = NULL;
824 int ret = ENOMEM;
826 ev = samba_tevent_context_init(mem_ctx);
827 if (ev == NULL) {
828 goto fail;
830 req = local_np_connect_send(
833 pipename,
834 transport,
835 remote_client_name,
836 remote_client_addr,
837 local_server_name,
838 local_server_addr,
839 session_info,
840 need_idle_server);
841 if (req == NULL) {
842 goto fail;
844 if (!tevent_req_poll_unix(req, ev, &ret)) {
845 goto fail;
847 ret = local_np_connect_recv(req, mem_ctx, pstream);
848 fail:
849 TALLOC_FREE(req);
850 TALLOC_FREE(ev);
851 return ret;