Line data Source code
1 : /*
2 : * Unix SMB/CIFS implementation.
3 : *
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.
8 : *
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.
13 : *
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/>.
16 : */
17 :
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"
30 :
31 : /**
32 : * @file local_np.c
33 : *
34 : * Connect to a local named pipe by connecting to
35 : * samba-dcerpcd. Start samba-dcerpcd if it isn't
36 : * already running.
37 : */
38 :
39 : extern bool override_logfile;
40 :
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;
46 :
47 : DATA_BLOB npa_blob;
48 : struct iovec iov;
49 :
50 : int sock;
51 : struct tevent_req *subreq;
52 : struct tstream_context *transport;
53 : struct tstream_context *npa_stream;
54 : };
55 :
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);
63 :
64 47840 : 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)
69 : {
70 47840 : struct tevent_req *req = NULL;
71 47840 : struct np_sock_connect_state *state = NULL;
72 620 : size_t len;
73 620 : int ret;
74 620 : bool ok;
75 :
76 47840 : req = tevent_req_create(mem_ctx, &state, struct np_sock_connect_state);
77 47840 : if (req == NULL) {
78 0 : return NULL;
79 : }
80 47840 : state->ev = ev;
81 47840 : state->npa_req = npa_req;
82 47840 : state->sock = -1;
83 47840 : state->addr.u.un.sun_family = AF_UNIX;
84 :
85 47840 : state->npa_rep = talloc_zero(state, struct named_pipe_auth_rep);
86 47840 : if (tevent_req_nomem(state->npa_rep, req)) {
87 0 : return tevent_req_post(req, ev);
88 : }
89 :
90 47840 : tevent_req_set_cleanup_fn(req, np_sock_connect_cleanup);
91 :
92 47840 : state->addr.sa_socklen = sizeof(struct sockaddr_un);
93 47840 : len = strlcpy(state->addr.u.un.sun_path,
94 : sockpath,
95 : sizeof(state->addr.u.un.sun_path));
96 47840 : if (len >= sizeof(state->addr.u.un.sun_path)) {
97 0 : tevent_req_error(req, ENAMETOOLONG);
98 0 : return tevent_req_post(req, ev);
99 : }
100 :
101 47840 : state->sock = socket(AF_UNIX, SOCK_STREAM, 0);
102 47840 : if (state->sock == -1) {
103 0 : tevent_req_error(req, errno);
104 0 : return tevent_req_post(req, ev);
105 : }
106 :
107 47840 : ret = set_blocking(state->sock, true);
108 47840 : if (ret == -1) {
109 0 : tevent_req_error(req, errno);
110 0 : return tevent_req_post(req, ev);
111 : }
112 47840 : ok = set_close_on_exec(state->sock);
113 47840 : if (!ok) {
114 0 : tevent_req_error(req, errno);
115 0 : return tevent_req_post(req, ev);
116 : }
117 :
118 95680 : state->subreq = async_connect_send(
119 : state,
120 : ev,
121 47220 : state->sock,
122 47840 : &state->addr.u.sa,
123 47840 : state->addr.sa_socklen,
124 : np_sock_connect_before,
125 : np_sock_connect_after,
126 : NULL);
127 47840 : if (tevent_req_nomem(state->subreq, req)) {
128 0 : return tevent_req_post(req, ev);
129 : }
130 47840 : tevent_req_set_callback(state->subreq, np_sock_connect_connected, req);
131 :
132 47840 : return req;
133 : }
134 :
135 95680 : static void np_sock_connect_cleanup(
136 : struct tevent_req *req, enum tevent_req_state req_state)
137 : {
138 95680 : struct np_sock_connect_state *state = tevent_req_data(
139 : req, struct np_sock_connect_state);
140 :
141 95680 : TALLOC_FREE(state->subreq);
142 95680 : TALLOC_FREE(state->transport);
143 :
144 95680 : if (state->sock != -1) {
145 269 : close(state->sock);
146 269 : state->sock = -1;
147 : }
148 95680 : }
149 :
150 47840 : static void np_sock_connect_before(void *private_data)
151 : {
152 47840 : become_root();
153 47840 : }
154 :
155 47840 : static void np_sock_connect_after(void *private_data)
156 : {
157 47840 : unbecome_root();
158 47840 : }
159 :
160 47840 : static void np_sock_connect_connected(struct tevent_req *subreq)
161 : {
162 47840 : struct tevent_req *req = tevent_req_callback_data(
163 : subreq, struct tevent_req);
164 47840 : struct np_sock_connect_state *state = tevent_req_data(
165 : req, struct np_sock_connect_state);
166 620 : enum ndr_err_code ndr_err;
167 620 : int ret, err;
168 :
169 47840 : SMB_ASSERT(subreq == state->subreq);
170 :
171 47840 : ret = async_connect_recv(subreq, &err);
172 47840 : TALLOC_FREE(subreq);
173 47840 : state->subreq = NULL;
174 47840 : if (ret == -1) {
175 269 : DBG_DEBUG("async_connect_recv returned %s\n", strerror(err));
176 269 : tevent_req_error(req, err);
177 269 : return;
178 : }
179 :
180 : /*
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.
185 : */
186 47571 : ret = set_blocking(state->sock, false);
187 47571 : if (ret == -1) {
188 0 : tevent_req_error(req, errno);
189 0 : return;
190 : }
191 :
192 47571 : ret = tstream_bsd_existing_socket(
193 : state, state->sock, &state->transport);
194 47571 : if (ret == -1) {
195 0 : err = errno;
196 0 : DBG_DEBUG("tstream_bsd_existing_socket failed: %s\n",
197 : strerror(err));
198 0 : tevent_req_error(req, err);
199 0 : return;
200 : }
201 47571 : state->sock = -1;
202 :
203 48191 : ndr_err = ndr_push_struct_blob(
204 : &state->npa_blob,
205 : state,
206 47571 : state->npa_req,
207 : (ndr_push_flags_fn_t)ndr_push_named_pipe_auth_req);
208 47571 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
209 0 : DBG_DEBUG("ndr_push_struct_blob failed: %s\n",
210 : ndr_errstr(ndr_err));
211 0 : tevent_req_error(req, ndr_map_error2errno(ndr_err));
212 0 : return;
213 : }
214 47571 : state->iov = (struct iovec) {
215 47571 : .iov_base = state->npa_blob.data,
216 47571 : .iov_len = state->npa_blob.length,
217 : };
218 :
219 48191 : subreq = tstream_writev_send(
220 47571 : state, state->ev, state->transport, &state->iov, 1);
221 47571 : if (tevent_req_nomem(subreq, req)) {
222 0 : return;
223 : }
224 47571 : tevent_req_set_callback(subreq, np_sock_connect_written, req);
225 : }
226 :
227 47571 : static void np_sock_connect_written(struct tevent_req *subreq)
228 : {
229 47571 : struct tevent_req *req = tevent_req_callback_data(
230 : subreq, struct tevent_req);
231 47571 : struct np_sock_connect_state *state = tevent_req_data(
232 : req, struct np_sock_connect_state);
233 620 : int ret, err;
234 :
235 47571 : ret = tstream_writev_recv(subreq, &err);
236 47571 : TALLOC_FREE(subreq);
237 47571 : if (ret == -1) {
238 0 : DBG_DEBUG("tstream_writev_recv returned %s\n", strerror(err));
239 0 : tevent_req_error(req, err);
240 0 : return;
241 : }
242 :
243 47571 : subreq = tstream_u32_read_send(
244 : state, state->ev, 0x00FFFFFF, state->transport);
245 47571 : if (tevent_req_nomem(subreq, req)) {
246 0 : return;
247 : }
248 47571 : tevent_req_set_callback(subreq, np_sock_connect_read_done, req);
249 : }
250 :
251 47571 : static void np_sock_connect_read_done(struct tevent_req *subreq)
252 : {
253 47571 : struct tevent_req *req = tevent_req_callback_data(
254 : subreq, struct tevent_req);
255 47571 : struct np_sock_connect_state *state = tevent_req_data(
256 : req, struct np_sock_connect_state);
257 620 : DATA_BLOB in;
258 620 : int ret;
259 620 : enum ndr_err_code ndr_err;
260 :
261 47571 : ret = tstream_u32_read_recv(subreq, state, &in.data, &in.length);
262 47571 : TALLOC_FREE(subreq);
263 47571 : if (tevent_req_error(req, ret)) {
264 0 : return;
265 : }
266 :
267 48191 : ndr_err = ndr_pull_struct_blob_all(
268 : &in,
269 46951 : state->npa_rep,
270 47571 : state->npa_rep,
271 : (ndr_pull_flags_fn_t)ndr_pull_named_pipe_auth_rep);
272 47571 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
273 0 : DBG_DEBUG("ndr_pull_named_pipe_auth_rep failed: %s\n",
274 : ndr_errstr(ndr_err));
275 0 : tevent_req_error(req, ndr_map_error2errno(ndr_err));
276 0 : return;
277 : }
278 47571 : if (state->npa_rep->level != 8) {
279 0 : DBG_DEBUG("npa level = %" PRIu32 ", expected 8\n",
280 : state->npa_rep->level);
281 0 : tevent_req_error(req, EIO);
282 0 : return;
283 : }
284 :
285 47571 : ret = tstream_npa_existing_stream(state,
286 : &state->transport,
287 : state->npa_rep->info.info8.file_type,
288 : &state->npa_stream);
289 47571 : if (ret == -1) {
290 0 : ret = errno;
291 0 : DBG_DEBUG("tstream_npa_existing_stream failed: %s\n",
292 : strerror(ret));
293 0 : tevent_req_error(req, ret);
294 0 : return;
295 : }
296 :
297 47571 : tevent_req_done(req);
298 : }
299 :
300 47840 : static int np_sock_connect_recv(
301 : struct tevent_req *req,
302 : TALLOC_CTX *mem_ctx,
303 : struct tstream_context **stream)
304 : {
305 47840 : struct np_sock_connect_state *state = tevent_req_data(
306 : req, struct np_sock_connect_state);
307 620 : int err;
308 :
309 47840 : if (tevent_req_is_unix_error(req, &err)) {
310 269 : tevent_req_received(req);
311 269 : return err;
312 : }
313 47571 : *stream = talloc_move(mem_ctx, &state->npa_stream);
314 47571 : tevent_req_received(req);
315 47571 : return 0;
316 : }
317 :
318 : struct start_rpc_host_state {
319 : int ready_fd;
320 : struct tevent_req *read_ready_req;
321 : };
322 :
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);
326 :
327 : /*
328 : * Start samba-dcerpcd and wait for it to report ready.
329 : */
330 128 : static struct tevent_req *start_rpc_host_send(
331 : TALLOC_CTX *mem_ctx, struct tevent_context *ev)
332 : {
333 128 : struct tevent_req *req = NULL, *subreq = NULL;
334 128 : struct start_rpc_host_state *state = NULL;
335 0 : int ret;
336 128 : int ready_fds[2] = { -1, -1 };
337 128 : char **argv = NULL;
338 0 : pid_t pid;
339 0 : bool ok;
340 :
341 128 : req = tevent_req_create(
342 : mem_ctx, &state, struct start_rpc_host_state);
343 128 : if (req == NULL) {
344 0 : return NULL;
345 : }
346 :
347 128 : ret = pipe(ready_fds);
348 128 : if (ret == -1) {
349 0 : ret = errno;
350 0 : DBG_DEBUG("pipe() failed: %s\n", strerror(ret));
351 0 : goto fail;
352 : }
353 :
354 128 : ok = smb_set_close_on_exec(ready_fds[0]);
355 128 : if (!ok) {
356 0 : ret = errno;
357 0 : DBG_DEBUG("smb_set_close_on_exec failed: %s\n",
358 : strerror(ret));
359 0 : goto fail;
360 : }
361 :
362 128 : argv = str_list_make_empty(mem_ctx);
363 128 : str_list_add_printf(
364 : &argv, "%s/samba-dcerpcd", get_dyn_SAMBA_LIBEXECDIR());
365 128 : if (!is_default_dyn_CONFIGFILE()) {
366 128 : str_list_add_printf(
367 : &argv, "--configfile=%s", get_dyn_CONFIGFILE());
368 : }
369 128 : str_list_add_printf(&argv, "--libexec-rpcds");
370 128 : str_list_add_printf(&argv, "--ready-signal-fd=%d", ready_fds[1]);
371 128 : str_list_add_printf(&argv, "--np-helper");
372 128 : str_list_add_printf(
373 : &argv, "--debuglevel=%d", debuglevel_get_class(DBGC_RPC_SRV));
374 128 : if (!is_default_dyn_LOGFILEBASE()) {
375 45 : str_list_add_printf(
376 : &argv, "--log-basename=%s", get_dyn_LOGFILEBASE());
377 : }
378 128 : if (argv == NULL) {
379 0 : errno = ENOMEM;
380 0 : goto fail;
381 : }
382 :
383 128 : become_root();
384 128 : ret = posix_spawn(&pid, argv[0], NULL, NULL, argv, environ);
385 128 : unbecome_root();
386 128 : if (ret != 0) {
387 0 : DBG_DEBUG("posix_spawn() failed: %s\n", strerror(ret));
388 0 : goto fail;
389 : }
390 :
391 128 : state->ready_fd = ready_fds[0];
392 128 : ready_fds[0] = -1;
393 128 : tevent_req_set_cleanup_fn(req, start_rpc_host_cleanup);
394 :
395 128 : close(ready_fds[1]);
396 128 : ready_fds[1] = -1;
397 :
398 128 : subreq = read_packet_send(state, ev, state->ready_fd, 1, NULL, NULL);
399 128 : if (tevent_req_nomem(subreq, req)) {
400 0 : return tevent_req_post(req, ev);
401 : }
402 128 : tevent_req_set_callback(subreq, start_rpc_host_ready, req);
403 128 : return req;
404 :
405 0 : fail:
406 0 : if (ready_fds[0] != -1) {
407 0 : close(ready_fds[0]);
408 0 : ready_fds[0] = -1;
409 : }
410 0 : if (ready_fds[1] != -1) {
411 0 : close(ready_fds[1]);
412 0 : ready_fds[1] = -1;
413 : }
414 0 : tevent_req_error(req, ret);
415 0 : return tevent_req_post(req, ev);
416 : }
417 :
418 256 : static void start_rpc_host_cleanup(
419 : struct tevent_req *req, enum tevent_req_state req_state)
420 : {
421 256 : struct start_rpc_host_state *state = tevent_req_data(
422 : req, struct start_rpc_host_state);
423 :
424 256 : if (state->ready_fd != -1) {
425 0 : close(state->ready_fd);
426 0 : state->ready_fd = -1;
427 : }
428 256 : }
429 :
430 128 : static void start_rpc_host_ready(struct tevent_req *subreq)
431 : {
432 128 : struct tevent_req *req = tevent_req_callback_data(
433 : subreq, struct tevent_req);
434 128 : struct start_rpc_host_state *state = tevent_req_data(
435 : req, struct start_rpc_host_state);
436 0 : uint8_t *buf;
437 0 : int err;
438 0 : ssize_t nread;
439 :
440 128 : nread = read_packet_recv(subreq, state, &buf, &err);
441 128 : TALLOC_FREE(subreq);
442 128 : if (nread == -1) {
443 0 : tevent_req_error(req, err);
444 0 : return;
445 : }
446 :
447 128 : close(state->ready_fd);
448 128 : state->ready_fd = -1;
449 :
450 128 : tevent_req_done(req);
451 : }
452 :
453 128 : static int start_rpc_host_recv(struct tevent_req *req)
454 : {
455 128 : return tevent_req_simple_recv_unix(req);
456 : }
457 :
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;
463 : };
464 :
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);
468 :
469 : /**
470 : * @brief Async connect to a local named pipe RPC interface
471 : *
472 : * Start "samba-dcerpcd" on demand if it does not exist
473 : *
474 : * @param[in] mem_ctx The memory context to use.
475 : * @param[in] ev The tevent context to use.
476 : *
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
485 : */
486 :
487 47722 : 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)
498 : {
499 47722 : struct tevent_req *req = NULL, *subreq = NULL;
500 47722 : struct local_np_connect_state *state = NULL;
501 47722 : struct named_pipe_auth_req_info8 *i8 = NULL;
502 47722 : const char *socket_dir = NULL;
503 47722 : char *lower_case_pipename = NULL;
504 47722 : struct dom_sid npa_sid = global_sid_Samba_NPA_Flags;
505 47722 : uint32_t npa_flags = 0;
506 47722 : struct security_token *token = NULL;
507 620 : NTSTATUS status;
508 620 : size_t num_npa_sids;
509 620 : bool ok;
510 :
511 47722 : req = tevent_req_create(
512 : mem_ctx, &state, struct local_np_connect_state);
513 47722 : if (req == NULL) {
514 0 : return NULL;
515 : }
516 47722 : state->ev = ev;
517 :
518 620 : num_npa_sids =
519 47722 : security_token_count_flag_sids(session_info->security_token,
520 : &npa_sid,
521 : 1,
522 : NULL);
523 47722 : if (num_npa_sids != 0) {
524 0 : DBG_ERR("ERROR: %zu NPA Flags SIDs have already been "
525 : "detected in the security token!\n",
526 : num_npa_sids);
527 0 : tevent_req_error(req, EACCES);
528 0 : return tevent_req_post(req, ev);
529 : }
530 :
531 47722 : socket_dir = lp_parm_const_string(
532 : GLOBAL_SECTION_SNUM, "external_rpc_pipe", "socket_dir",
533 : lp_ncalrpc_dir());
534 47722 : if (socket_dir == NULL) {
535 0 : DBG_DEBUG("external_rpc_pipe:socket_dir not set\n");
536 0 : tevent_req_error(req, EINVAL);
537 0 : return tevent_req_post(req, ev);
538 : }
539 :
540 47722 : lower_case_pipename = strlower_talloc(state, pipename);
541 47722 : if (tevent_req_nomem(lower_case_pipename, req)) {
542 0 : return tevent_req_post(req, ev);
543 : }
544 :
545 : /*
546 : * Ensure we cannot process a path that exits
547 : * the socket_dir.
548 : */
549 47722 : if (ISDOTDOT(lower_case_pipename) ||
550 47722 : (strchr(lower_case_pipename, '/')!=NULL))
551 : {
552 10 : DBG_DEBUG("attempt to connect to invalid pipe pathname %s\n",
553 : lower_case_pipename);
554 10 : tevent_req_error(req, ENOENT);
555 10 : return tevent_req_post(req, ev);
556 : }
557 :
558 47712 : state->socketpath = talloc_asprintf(
559 : state, "%s/np/%s", socket_dir, lower_case_pipename);
560 47712 : if (tevent_req_nomem(state->socketpath, req)) {
561 0 : return tevent_req_post(req, ev);
562 : }
563 47712 : TALLOC_FREE(lower_case_pipename);
564 :
565 47712 : state->npa_req = talloc_zero(state, struct named_pipe_auth_req);
566 47712 : if (tevent_req_nomem(state->npa_req, req)) {
567 0 : return tevent_req_post(req, ev);
568 : }
569 47712 : state->npa_req->level = 8;
570 :
571 47712 : i8 = &state->npa_req->info.info8;
572 :
573 47712 : i8->transport = transport;
574 :
575 : /* we don't have "int" in IDL, make sure we don't overflow */
576 47712 : SMB_ASSERT(i8->transport == transport);
577 :
578 47712 : if (remote_client_name == NULL) {
579 47712 : remote_client_name = get_myname(state->npa_req);
580 47712 : if (remote_client_name == NULL) {
581 0 : tevent_req_error(req, errno);
582 0 : return tevent_req_post(req, ev);
583 : }
584 : }
585 47712 : i8->remote_client_name = remote_client_name;
586 :
587 47712 : if (remote_client_addr == NULL) {
588 0 : struct tsocket_address *addr = NULL;
589 0 : int ret = tsocket_address_inet_from_strings(
590 : state->npa_req, "ip", NULL, 0, &addr);
591 0 : if (ret != 0) {
592 0 : tevent_req_error(req, errno);
593 0 : return tevent_req_post(req, ev);
594 : }
595 0 : remote_client_addr = addr;
596 : }
597 48332 : i8->remote_client_addr =
598 47712 : tsocket_address_inet_addr_string(remote_client_addr,
599 47712 : state->npa_req);
600 47712 : if (i8->remote_client_addr == NULL) {
601 0 : tevent_req_error(req, errno);
602 0 : return tevent_req_post(req, ev);
603 : }
604 47712 : i8->remote_client_port = tsocket_address_inet_port(remote_client_addr);
605 :
606 47712 : if (local_server_name == NULL) {
607 47712 : local_server_name = remote_client_name;
608 : }
609 47712 : i8->local_server_name = local_server_name;
610 :
611 47712 : if (local_server_addr == NULL) {
612 30588 : struct tsocket_address *addr = NULL;
613 30588 : int ret = tsocket_address_inet_from_strings(
614 : state->npa_req, "ip", NULL, 0, &addr);
615 30588 : if (ret != 0) {
616 0 : tevent_req_error(req, errno);
617 0 : return tevent_req_post(req, ev);
618 : }
619 30588 : local_server_addr = addr;
620 : }
621 48332 : i8->local_server_addr =
622 47712 : tsocket_address_inet_addr_string(local_server_addr,
623 47712 : state->npa_req);
624 47712 : if (i8->local_server_addr == NULL) {
625 0 : tevent_req_error(req, errno);
626 0 : return tevent_req_post(req, ev);
627 : }
628 47712 : i8->local_server_port = tsocket_address_inet_port(local_server_addr);
629 :
630 47712 : i8->session_info = talloc_zero(state->npa_req,
631 : struct auth_session_info_transport);
632 47712 : if (tevent_req_nomem(i8->session_info, req)) {
633 0 : return tevent_req_post(req, ev);
634 : }
635 :
636 95424 : i8->session_info->session_info =
637 47712 : copy_session_info(i8->session_info, session_info);
638 47712 : if (tevent_req_nomem(i8->session_info->session_info, req)) {
639 0 : return tevent_req_post(req, ev);
640 : }
641 :
642 47712 : if (need_idle_server) {
643 30672 : npa_flags |= SAMBA_NPA_FLAGS_NEED_IDLE;
644 : }
645 :
646 47712 : ok = winbind_env_set();
647 47712 : if (ok) {
648 0 : npa_flags |= SAMBA_NPA_FLAGS_WINBIND_OFF;
649 : }
650 :
651 47712 : ok = sid_append_rid(&npa_sid, npa_flags);
652 47712 : if (!ok) {
653 0 : tevent_req_error(req, EINVAL);
654 0 : return tevent_req_post(req, ev);
655 : }
656 :
657 47712 : token = i8->session_info->session_info->security_token;
658 :
659 47712 : status = add_sid_to_array_unique(token,
660 : &npa_sid,
661 : &token->sids,
662 : &token->num_sids);
663 47712 : if (!NT_STATUS_IS_OK(status)) {
664 0 : tevent_req_oom(req);
665 0 : return tevent_req_post(req, ev);
666 : }
667 :
668 48332 : subreq = np_sock_connect_send(
669 47712 : state, state->ev, state->socketpath, state->npa_req);
670 47712 : if (tevent_req_nomem(subreq, req)) {
671 0 : return tevent_req_post(req, ev);
672 : }
673 47712 : tevent_req_set_callback(subreq, local_np_connect_connected, req);
674 :
675 47712 : return req;
676 : }
677 :
678 47712 : static void local_np_connect_connected(struct tevent_req *subreq)
679 : {
680 47712 : struct tevent_req *req = tevent_req_callback_data(
681 : subreq, struct tevent_req);
682 47712 : struct local_np_connect_state *state = tevent_req_data(
683 : req, struct local_np_connect_state);
684 620 : int ret;
685 :
686 47712 : ret = np_sock_connect_recv(subreq, state, &state->npa_stream);
687 47712 : TALLOC_FREE(subreq);
688 :
689 47712 : if (ret == 0) {
690 47514 : tevent_req_done(req);
691 47514 : return;
692 : }
693 :
694 198 : DBG_DEBUG("np_sock_connect failed: %s\n", strerror(ret));
695 :
696 198 : if (!lp_rpc_start_on_demand_helpers()) {
697 : /*
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.
702 : */
703 70 : 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 70 : tevent_req_error(req, ret);
708 70 : return;
709 : }
710 :
711 : /*
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.
716 : */
717 128 : subreq = start_rpc_host_send(state, state->ev);
718 128 : if (tevent_req_nomem(subreq, req)) {
719 0 : return;
720 : }
721 128 : tevent_req_set_callback(subreq, local_np_connect_started, req);
722 : }
723 :
724 128 : static void local_np_connect_started(struct tevent_req *subreq)
725 : {
726 128 : struct tevent_req *req = tevent_req_callback_data(
727 : subreq, struct tevent_req);
728 128 : struct local_np_connect_state *state = tevent_req_data(
729 : req, struct local_np_connect_state);
730 0 : int ret;
731 :
732 128 : ret = start_rpc_host_recv(subreq);
733 128 : TALLOC_FREE(subreq);
734 128 : if (tevent_req_error(req, ret)) {
735 0 : DBG_DEBUG("start_rpc_host_recv failed: %s\n",
736 : strerror(ret));
737 0 : return;
738 : }
739 :
740 128 : subreq = np_sock_connect_send(
741 128 : state, state->ev, state->socketpath, state->npa_req);
742 128 : if (tevent_req_nomem(subreq, req)) {
743 0 : return;
744 : }
745 128 : tevent_req_set_callback(subreq, local_np_connect_retried, req);
746 : }
747 :
748 128 : static void local_np_connect_retried(struct tevent_req *subreq)
749 : {
750 128 : struct tevent_req *req = tevent_req_callback_data(
751 : subreq, struct tevent_req);
752 128 : struct local_np_connect_state *state = tevent_req_data(
753 : req, struct local_np_connect_state);
754 0 : int ret;
755 :
756 128 : ret = np_sock_connect_recv(subreq, state, &state->npa_stream);
757 128 : TALLOC_FREE(subreq);
758 128 : if (tevent_req_error(req, ret)) {
759 71 : return;
760 : }
761 57 : tevent_req_done(req);
762 : }
763 :
764 : /**
765 : * @brief Receive handle to a local named pipe RPC interface
766 : *
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
771 : *
772 : * @return 0/errno
773 : */
774 :
775 47722 : int local_np_connect_recv(
776 : struct tevent_req *req,
777 : TALLOC_CTX *mem_ctx,
778 : struct tstream_context **pstream)
779 : {
780 47722 : struct local_np_connect_state *state = tevent_req_data(
781 : req, struct local_np_connect_state);
782 620 : int err;
783 :
784 47722 : if (tevent_req_is_unix_error(req, &err)) {
785 151 : tevent_req_received(req);
786 151 : return err;
787 : }
788 :
789 47571 : *pstream = talloc_move(mem_ctx, &state->npa_stream);
790 47571 : return 0;
791 : }
792 :
793 : /**
794 : * @brief Sync connect to a local named pipe RPC interface
795 : *
796 : * Start "samba-dcerpcd" on demand if it does not exist
797 : *
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
808 : */
809 :
810 47722 : 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)
821 : {
822 47722 : struct tevent_context *ev = NULL;
823 47722 : struct tevent_req *req = NULL;
824 47722 : int ret = ENOMEM;
825 :
826 47722 : ev = samba_tevent_context_init(mem_ctx);
827 47722 : if (ev == NULL) {
828 0 : goto fail;
829 : }
830 47722 : req = local_np_connect_send(
831 : ev,
832 : ev,
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 47722 : if (req == NULL) {
842 0 : goto fail;
843 : }
844 47722 : if (!tevent_req_poll_unix(req, ev, &ret)) {
845 0 : goto fail;
846 : }
847 47722 : ret = local_np_connect_recv(req, mem_ctx, pstream);
848 47722 : fail:
849 47722 : TALLOC_FREE(req);
850 47722 : TALLOC_FREE(ev);
851 47722 : return ret;
852 : }
|