2 Unix SMB/CIFS implementation.
4 dcerpc connect functions
6 Copyright (C) Andrew Tridgell 2003
7 Copyright (C) Jelmer Vernooij 2004
8 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
9 Copyright (C) Rafal Szczesniak 2005
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 #include "libcli/composite/composite.h"
29 #include "libcli/smb_composite/smb_composite.h"
30 #include "lib/events/events.h"
31 #include "libcli/smb2/smb2.h"
32 #include "libcli/smb2/smb2_calls.h"
33 #include "librpc/rpc/dcerpc.h"
34 #include "auth/credentials/credentials.h"
35 #include "auth/credentials/credentials_krb5.h"
38 struct pipe_np_smb_state
{
39 struct smb_composite_connect conn
;
40 struct smbcli_tree
*tree
;
41 struct dcerpc_pipe_connect io
;
46 Stage 3 of ncacn_np_smb: Named pipe opened (or not)
48 static void continue_pipe_open_smb(struct composite_context
*ctx
)
50 struct composite_context
*c
= talloc_get_type(ctx
->async
.private_data
,
51 struct composite_context
);
53 /* receive result of named pipe open request on smb */
54 c
->status
= dcerpc_pipe_open_smb_recv(ctx
);
55 if (!composite_is_ok(c
)) return;
62 Stage 2 of ncacn_np_smb: Open a named pipe after successful smb connection
64 static void continue_smb_connect(struct composite_context
*ctx
)
66 struct composite_context
*open_ctx
;
67 struct composite_context
*c
= talloc_get_type(ctx
->async
.private_data
,
68 struct composite_context
);
69 struct pipe_np_smb_state
*s
= talloc_get_type(c
->private_data
,
70 struct pipe_np_smb_state
);
72 /* receive result of smb connect request */
73 c
->status
= smb_composite_connect_recv(ctx
, c
);
74 if (!composite_is_ok(c
)) return;
76 /* prepare named pipe open parameters */
77 s
->tree
= s
->conn
.out
.tree
;
78 s
->io
.pipe_name
= s
->io
.binding
->endpoint
;
80 /* send named pipe open request */
81 open_ctx
= dcerpc_pipe_open_smb_send(s
->io
.pipe
->conn
, s
->tree
, s
->io
.pipe_name
);
82 if (composite_nomem(open_ctx
, c
)) return;
84 composite_continue(c
, open_ctx
, continue_pipe_open_smb
, c
);
89 Initiate async open of a rpc connection to a rpc pipe on SMB using
90 the binding structure to determine the endpoint and options
92 static struct composite_context
*dcerpc_pipe_connect_ncacn_np_smb_send(TALLOC_CTX
*mem_ctx
,
93 struct dcerpc_pipe_connect
*io
)
95 struct composite_context
*c
;
96 struct pipe_np_smb_state
*s
;
97 struct composite_context
*conn_req
;
98 struct smb_composite_connect
*conn
;
100 /* composite context allocation and setup */
101 c
= composite_create(mem_ctx
, io
->pipe
->conn
->event_ctx
);
102 if (c
== NULL
) return NULL
;
104 s
= talloc_zero(c
, struct pipe_np_smb_state
);
105 if (composite_nomem(s
, c
)) return c
;
111 /* prepare smb connection parameters: we're connecting to IPC$ share on
113 conn
->in
.dest_host
= s
->io
.binding
->host
;
115 conn
->in
.called_name
= s
->io
.binding
->target_hostname
;
116 conn
->in
.service
= "IPC$";
117 conn
->in
.service_type
= NULL
;
118 conn
->in
.workgroup
= lp_workgroup();
121 * provide proper credentials - user supplied, but allow a
122 * fallback to anonymous if this is an schannel connection
123 * (might be NT4 not allowing machine logins at session
126 s
->conn
.in
.credentials
= s
->io
.creds
;
127 if (s
->io
.binding
->flags
& DCERPC_SCHANNEL
) {
128 conn
->in
.fallback_to_anonymous
= True
;
130 conn
->in
.fallback_to_anonymous
= False
;
133 /* send smb connect request */
134 conn_req
= smb_composite_connect_send(conn
, s
->io
.pipe
->conn
, s
->io
.pipe
->conn
->event_ctx
);
135 if (composite_nomem(conn_req
, c
)) return c
;
137 composite_continue(c
, conn_req
, continue_smb_connect
, c
);
143 Receive result of a rpc connection to a rpc pipe on SMB
145 static NTSTATUS
dcerpc_pipe_connect_ncacn_np_smb_recv(struct composite_context
*c
)
147 NTSTATUS status
= composite_wait(c
);
154 struct pipe_np_smb2_state
{
155 struct smb2_tree
*tree
;
156 struct dcerpc_pipe_connect io
;
161 Stage 3 of ncacn_np_smb: Named pipe opened (or not)
163 static void continue_pipe_open_smb2(struct composite_context
*ctx
)
165 struct composite_context
*c
= talloc_get_type(ctx
->async
.private_data
,
166 struct composite_context
);
168 /* receive result of named pipe open request on smb2 */
169 c
->status
= dcerpc_pipe_open_smb2_recv(ctx
);
170 if (!composite_is_ok(c
)) return;
177 Stage 2 of ncacn_np_smb2: Open a named pipe after successful smb2 connection
179 static void continue_smb2_connect(struct composite_context
*ctx
)
181 struct composite_context
*open_req
;
182 struct composite_context
*c
= talloc_get_type(ctx
->async
.private_data
,
183 struct composite_context
);
184 struct pipe_np_smb2_state
*s
= talloc_get_type(c
->private_data
,
185 struct pipe_np_smb2_state
);
187 /* receive result of smb2 connect request */
188 c
->status
= smb2_connect_recv(ctx
, c
, &s
->tree
);
189 if (!composite_is_ok(c
)) return;
191 /* prepare named pipe open parameters */
192 s
->io
.pipe_name
= s
->io
.binding
->endpoint
;
194 /* send named pipe open request */
195 open_req
= dcerpc_pipe_open_smb2_send(s
->io
.pipe
->conn
, s
->tree
, s
->io
.pipe_name
);
196 if (composite_nomem(open_req
, c
)) return;
198 composite_continue(c
, open_req
, continue_pipe_open_smb2
, c
);
203 Initiate async open of a rpc connection request on SMB2 using
204 the binding structure to determine the endpoint and options
206 static struct composite_context
*dcerpc_pipe_connect_ncacn_np_smb2_send(TALLOC_CTX
*mem_ctx
,
207 struct dcerpc_pipe_connect
*io
)
209 struct composite_context
*c
;
210 struct pipe_np_smb2_state
*s
;
211 struct composite_context
*conn_req
;
213 /* composite context allocation and setup */
214 c
= composite_create(mem_ctx
, io
->pipe
->conn
->event_ctx
);
215 if (c
== NULL
) return NULL
;
217 s
= talloc_zero(c
, struct pipe_np_smb2_state
);
218 if (composite_nomem(s
, c
)) return c
;
224 * provide proper credentials - user supplied or anonymous in case this is
225 * schannel connection
227 if (s
->io
.binding
->flags
& DCERPC_SCHANNEL
) {
228 s
->io
.creds
= cli_credentials_init(mem_ctx
);
229 if (composite_nomem(s
->io
.creds
, c
)) return c
;
231 cli_credentials_set_anonymous(s
->io
.creds
);
232 cli_credentials_guess(s
->io
.creds
);
235 /* send smb2 connect request */
236 conn_req
= smb2_connect_send(mem_ctx
, s
->io
.binding
->host
, "IPC$", s
->io
.creds
,
238 composite_continue(c
, conn_req
, continue_smb2_connect
, c
);
244 Receive result of a rpc connection to a rpc pipe on SMB2
246 static NTSTATUS
dcerpc_pipe_connect_ncacn_np_smb2_recv(struct composite_context
*c
)
248 NTSTATUS status
= composite_wait(c
);
255 struct pipe_ip_tcp_state
{
256 struct dcerpc_pipe_connect io
;
258 const char *target_hostname
;
264 Stage 2 of ncacn_ip_tcp: rpc pipe opened (or not)
266 static void continue_pipe_open_ncacn_ip_tcp(struct composite_context
*ctx
)
268 struct composite_context
*c
= talloc_get_type(ctx
->async
.private_data
,
269 struct composite_context
);
271 /* receive result of named pipe open request on tcp/ip */
272 c
->status
= dcerpc_pipe_open_tcp_recv(ctx
);
273 if (!composite_is_ok(c
)) return;
280 Initiate async open of a rpc connection to a rpc pipe on TCP/IP using
281 the binding structure to determine the endpoint and options
283 static struct composite_context
* dcerpc_pipe_connect_ncacn_ip_tcp_send(TALLOC_CTX
*mem_ctx
,
284 struct dcerpc_pipe_connect
*io
)
286 struct composite_context
*c
;
287 struct pipe_ip_tcp_state
*s
;
288 struct composite_context
*pipe_req
;
290 /* composite context allocation and setup */
291 c
= composite_create(mem_ctx
, io
->pipe
->conn
->event_ctx
);
292 if (c
== NULL
) return NULL
;
294 s
= talloc_zero(c
, struct pipe_ip_tcp_state
);
295 if (composite_nomem(s
, c
)) return c
;
298 /* store input parameters in state structure */
300 s
->host
= talloc_reference(c
, io
->binding
->host
);
301 s
->target_hostname
= talloc_reference(c
, io
->binding
->target_hostname
);
302 /* port number is a binding endpoint here */
303 s
->port
= atoi(io
->binding
->endpoint
);
305 /* send pipe open request on tcp/ip */
306 pipe_req
= dcerpc_pipe_open_tcp_send(s
->io
.pipe
->conn
, s
->host
, s
->target_hostname
,
308 composite_continue(c
, pipe_req
, continue_pipe_open_ncacn_ip_tcp
, c
);
314 Receive result of a rpc connection to a rpc pipe on TCP/IP
316 static NTSTATUS
dcerpc_pipe_connect_ncacn_ip_tcp_recv(struct composite_context
*c
)
318 NTSTATUS status
= composite_wait(c
);
325 struct pipe_unix_state
{
326 struct dcerpc_pipe_connect io
;
332 Stage 2 of ncacn_unix: rpc pipe opened (or not)
334 static void continue_pipe_open_ncacn_unix_stream(struct composite_context
*ctx
)
336 struct composite_context
*c
= talloc_get_type(ctx
->async
.private_data
,
337 struct composite_context
);
339 /* receive result of pipe open request on unix socket */
340 c
->status
= dcerpc_pipe_open_unix_stream_recv(ctx
);
341 if (!composite_is_ok(c
)) return;
348 Initiate async open of a rpc connection to a rpc pipe on unix socket using
349 the binding structure to determine the endpoint and options
351 static struct composite_context
* dcerpc_pipe_connect_ncacn_unix_stream_send(TALLOC_CTX
*mem_ctx
,
352 struct dcerpc_pipe_connect
*io
)
354 struct composite_context
*c
;
355 struct pipe_unix_state
*s
;
356 struct composite_context
*pipe_req
;
358 /* composite context allocation and setup */
359 c
= composite_create(mem_ctx
, io
->pipe
->conn
->event_ctx
);
360 if (c
== NULL
) return NULL
;
362 s
= talloc_zero(c
, struct pipe_unix_state
);
363 if (composite_nomem(s
, c
)) return c
;
366 /* prepare pipe open parameters and store them in state structure
367 also, verify whether biding endpoint is not null */
370 if (!io
->binding
->endpoint
) {
371 DEBUG(0, ("Path to unix socket not specified\n"));
372 composite_error(c
, NT_STATUS_INVALID_PARAMETER
);
376 s
->path
= talloc_strdup(c
, io
->binding
->endpoint
); /* path is a binding endpoint here */
377 if (composite_nomem(s
->path
, c
)) return c
;
379 /* send pipe open request on unix socket */
380 pipe_req
= dcerpc_pipe_open_unix_stream_send(s
->io
.pipe
->conn
, s
->path
);
381 composite_continue(c
, pipe_req
, continue_pipe_open_ncacn_unix_stream
, c
);
387 Receive result of a rpc connection to a pipe on unix socket
389 static NTSTATUS
dcerpc_pipe_connect_ncacn_unix_stream_recv(struct composite_context
*c
)
391 NTSTATUS status
= composite_wait(c
);
398 struct pipe_ncalrpc_state
{
399 struct dcerpc_pipe_connect io
;
402 static NTSTATUS
dcerpc_pipe_connect_ncalrpc_recv(struct composite_context
*c
);
405 Stage 2 of ncalrpc: rpc pipe opened (or not)
407 static void continue_pipe_open_ncalrpc(struct composite_context
*ctx
)
409 struct composite_context
*c
= talloc_get_type(ctx
->async
.private_data
,
410 struct composite_context
);
412 /* receive result of pipe open request on ncalrpc */
413 c
->status
= dcerpc_pipe_connect_ncalrpc_recv(ctx
);
414 if (!composite_is_ok(c
)) return;
421 Initiate async open of a rpc connection request on NCALRPC using
422 the binding structure to determine the endpoint and options
424 static struct composite_context
* dcerpc_pipe_connect_ncalrpc_send(TALLOC_CTX
*mem_ctx
,
425 struct dcerpc_pipe_connect
*io
)
427 struct composite_context
*c
;
428 struct pipe_ncalrpc_state
*s
;
429 struct composite_context
*pipe_req
;
431 /* composite context allocation and setup */
432 c
= composite_create(mem_ctx
, io
->pipe
->conn
->event_ctx
);
433 if (c
== NULL
) return NULL
;
435 s
= talloc_zero(c
, struct pipe_ncalrpc_state
);
436 if (composite_nomem(s
, c
)) return c
;
439 /* store input parameters in state structure */
442 /* send pipe open request */
443 pipe_req
= dcerpc_pipe_open_pipe_send(s
->io
.pipe
->conn
, s
->io
.binding
->endpoint
);
444 composite_continue(c
, pipe_req
, continue_pipe_open_ncalrpc
, c
);
450 Receive result of a rpc connection to a rpc pipe on NCALRPC
452 static NTSTATUS
dcerpc_pipe_connect_ncalrpc_recv(struct composite_context
*c
)
454 NTSTATUS status
= composite_wait(c
);
461 struct pipe_connect_state
{
462 struct dcerpc_pipe
*pipe
;
463 struct dcerpc_binding
*binding
;
464 const struct dcerpc_interface_table
*table
;
465 struct cli_credentials
*credentials
;
469 static void continue_map_binding(struct composite_context
*ctx
);
470 static void continue_connect(struct composite_context
*c
, struct pipe_connect_state
*s
);
471 static void continue_pipe_connect_ncacn_np_smb2(struct composite_context
*ctx
);
472 static void continue_pipe_connect_ncacn_np_smb(struct composite_context
*ctx
);
473 static void continue_pipe_connect_ncacn_ip_tcp(struct composite_context
*ctx
);
474 static void continue_pipe_connect_ncacn_unix(struct composite_context
*ctx
);
475 static void continue_pipe_connect_ncalrpc(struct composite_context
*ctx
);
476 static void continue_pipe_connect(struct composite_context
*c
, struct pipe_connect_state
*s
);
477 static void continue_pipe_auth(struct composite_context
*ctx
);
481 Stage 2 of pipe_connect_b: Receive result of endpoint mapping
483 static void continue_map_binding(struct composite_context
*ctx
)
485 struct composite_context
*c
= talloc_get_type(ctx
->async
.private_data
,
486 struct composite_context
);
487 struct pipe_connect_state
*s
= talloc_get_type(c
->private_data
,
488 struct pipe_connect_state
);
490 c
->status
= dcerpc_epm_map_binding_recv(ctx
);
491 if (!composite_is_ok(c
)) return;
493 DEBUG(2,("Mapped to DCERPC endpoint %s\n", s
->binding
->endpoint
));
495 continue_connect(c
, s
);
500 Stage 2 of pipe_connect_b: Continue connection after endpoint is known
502 static void continue_connect(struct composite_context
*c
, struct pipe_connect_state
*s
)
504 struct dcerpc_pipe_connect pc
;
506 /* potential exits to another stage by sending an async request */
507 struct composite_context
*ncacn_np_smb2_req
;
508 struct composite_context
*ncacn_np_smb_req
;
509 struct composite_context
*ncacn_ip_tcp_req
;
510 struct composite_context
*ncacn_unix_req
;
511 struct composite_context
*ncalrpc_req
;
513 /* dcerpc pipe connect input parameters */
515 pc
.binding
= s
->binding
;
516 pc
.interface
= s
->table
;
517 pc
.creds
= s
->credentials
;
519 /* connect dcerpc pipe depending on required transport */
520 switch (s
->binding
->transport
) {
522 if (pc
.binding
->flags
& DCERPC_SMB2
) {
523 /* new varient of SMB a.k.a. SMB2 */
524 ncacn_np_smb2_req
= dcerpc_pipe_connect_ncacn_np_smb2_send(c
, &pc
);
525 composite_continue(c
, ncacn_np_smb2_req
, continue_pipe_connect_ncacn_np_smb2
, c
);
529 /* good old ordinary SMB */
530 ncacn_np_smb_req
= dcerpc_pipe_connect_ncacn_np_smb_send(c
, &pc
);
531 composite_continue(c
, ncacn_np_smb_req
, continue_pipe_connect_ncacn_np_smb
, c
);
537 ncacn_ip_tcp_req
= dcerpc_pipe_connect_ncacn_ip_tcp_send(c
, &pc
);
538 composite_continue(c
, ncacn_ip_tcp_req
, continue_pipe_connect_ncacn_ip_tcp
, c
);
541 case NCACN_UNIX_STREAM
:
542 ncacn_unix_req
= dcerpc_pipe_connect_ncacn_unix_stream_send(c
, &pc
);
543 composite_continue(c
, ncacn_unix_req
, continue_pipe_connect_ncacn_unix
, c
);
547 ncalrpc_req
= dcerpc_pipe_connect_ncalrpc_send(c
, &pc
);
548 composite_continue(c
, ncalrpc_req
, continue_pipe_connect_ncalrpc
, c
);
552 /* looks like a transport we don't support now */
553 composite_error(c
, NT_STATUS_NOT_SUPPORTED
);
559 Stage 3 of pipe_connect_b: Receive result of pipe connect request on
562 static void continue_pipe_connect_ncacn_np_smb2(struct composite_context
*ctx
)
564 struct composite_context
*c
= talloc_get_type(ctx
->async
.private_data
,
565 struct composite_context
);
566 struct pipe_connect_state
*s
= talloc_get_type(c
->private_data
,
567 struct pipe_connect_state
);
569 c
->status
= dcerpc_pipe_connect_ncacn_np_smb2_recv(ctx
);
570 if (!composite_is_ok(c
)) return;
572 continue_pipe_connect(c
, s
);
577 Stage 3 of pipe_connect_b: Receive result of pipe connect request on
580 static void continue_pipe_connect_ncacn_np_smb(struct composite_context
*ctx
)
582 struct composite_context
*c
= talloc_get_type(ctx
->async
.private_data
,
583 struct composite_context
);
584 struct pipe_connect_state
*s
= talloc_get_type(c
->private_data
,
585 struct pipe_connect_state
);
587 c
->status
= dcerpc_pipe_connect_ncacn_np_smb_recv(ctx
);
588 if (!composite_is_ok(c
)) return;
590 continue_pipe_connect(c
, s
);
595 Stage 3 of pipe_connect_b: Receive result of pipe connect request on tcp/ip
597 static void continue_pipe_connect_ncacn_ip_tcp(struct composite_context
*ctx
)
599 struct composite_context
*c
= talloc_get_type(ctx
->async
.private_data
,
600 struct composite_context
);
601 struct pipe_connect_state
*s
= talloc_get_type(c
->private_data
,
602 struct pipe_connect_state
);
604 c
->status
= dcerpc_pipe_connect_ncacn_ip_tcp_recv(ctx
);
605 if (!composite_is_ok(c
)) return;
607 continue_pipe_connect(c
, s
);
612 Stage 3 of pipe_connect_b: Receive result of pipe connect request on unix socket
614 static void continue_pipe_connect_ncacn_unix(struct composite_context
*ctx
)
616 struct composite_context
*c
= talloc_get_type(ctx
->async
.private_data
,
617 struct composite_context
);
618 struct pipe_connect_state
*s
= talloc_get_type(c
->private_data
,
619 struct pipe_connect_state
);
621 c
->status
= dcerpc_pipe_connect_ncacn_unix_stream_recv(ctx
);
622 if (!composite_is_ok(c
)) return;
624 continue_pipe_connect(c
, s
);
629 Stage 3 of pipe_connect_b: Receive result of pipe connect request on local rpc
631 static void continue_pipe_connect_ncalrpc(struct composite_context
*ctx
)
633 struct composite_context
*c
= talloc_get_type(ctx
->async
.private_data
,
634 struct composite_context
);
635 struct pipe_connect_state
*s
= talloc_get_type(c
->private_data
,
636 struct pipe_connect_state
);
638 c
->status
= dcerpc_pipe_connect_ncalrpc_recv(ctx
);
639 if (!composite_is_ok(c
)) return;
641 continue_pipe_connect(c
, s
);
646 Stage 4 of pipe_connect_b: Start an authentication on connected dcerpc pipe
647 depending on credentials and binding flags passed.
649 static void continue_pipe_connect(struct composite_context
*c
, struct pipe_connect_state
*s
)
651 struct composite_context
*auth_bind_req
;
653 s
->pipe
->binding
= s
->binding
;
654 if (!talloc_reference(s
->pipe
, s
->binding
)) {
655 composite_error(c
, NT_STATUS_NO_MEMORY
);
659 auth_bind_req
= dcerpc_pipe_auth_send(s
->pipe
, s
->binding
, s
->table
,
661 composite_continue(c
, auth_bind_req
, continue_pipe_auth
, c
);
666 Stage 5 of pipe_connect_b: Receive result of pipe authentication request
667 and say if all went ok
669 static void continue_pipe_auth(struct composite_context
*ctx
)
671 struct composite_context
*c
= talloc_get_type(ctx
->async
.private_data
,
672 struct composite_context
);
673 struct pipe_connect_state
*s
= talloc_get_type(c
->private_data
, struct pipe_connect_state
);
675 c
->status
= dcerpc_pipe_auth_recv(ctx
, s
, &s
->pipe
);
676 if (!composite_is_ok(c
)) return;
683 handle timeouts of a dcerpc connect
685 static void dcerpc_connect_timeout_handler(struct event_context
*ev
, struct timed_event
*te
,
686 struct timeval t
, void *private)
688 struct composite_context
*c
= talloc_get_type(private, struct composite_context
);
689 composite_error(c
, NT_STATUS_IO_TIMEOUT
);
693 start a request to open a rpc connection to a rpc pipe, using
694 specified binding structure to determine the endpoint and options
696 struct composite_context
* dcerpc_pipe_connect_b_send(TALLOC_CTX
*parent_ctx
,
697 struct dcerpc_binding
*binding
,
698 const struct dcerpc_interface_table
*table
,
699 struct cli_credentials
*credentials
,
700 struct event_context
*ev
)
702 struct composite_context
*c
;
703 struct pipe_connect_state
*s
;
704 struct event_context
*new_ev
= NULL
;
707 new_ev
= event_context_init(parent_ctx
);
708 if (new_ev
== NULL
) return NULL
;
712 /* composite context allocation and setup */
713 c
= composite_create(parent_ctx
, ev
);
718 talloc_steal(c
, new_ev
);
720 s
= talloc_zero(c
, struct pipe_connect_state
);
721 if (composite_nomem(s
, c
)) return c
;
724 /* initialise dcerpc pipe structure */
725 s
->pipe
= dcerpc_pipe_init(c
, ev
);
726 if (composite_nomem(s
->pipe
, c
)) return c
;
728 /* store parameters in state structure */
729 s
->binding
= binding
;
731 s
->credentials
= credentials
;
733 event_add_timed(c
->event_ctx
, c
,
734 timeval_current_ofs(DCERPC_REQUEST_TIMEOUT
, 0),
735 dcerpc_connect_timeout_handler
, c
);
737 switch (s
->binding
->transport
) {
741 if (!s
->binding
->endpoint
) {
742 struct composite_context
*binding_req
;
743 binding_req
= dcerpc_epm_map_binding_send(c
, s
->binding
, s
->table
,
744 s
->pipe
->conn
->event_ctx
);
745 composite_continue(c
, binding_req
, continue_map_binding
, c
);
753 continue_connect(c
, s
);
759 receive result of a request to open a rpc connection to a rpc pipe
761 NTSTATUS
dcerpc_pipe_connect_b_recv(struct composite_context
*c
, TALLOC_CTX
*mem_ctx
,
762 struct dcerpc_pipe
**p
)
765 struct pipe_connect_state
*s
;
767 status
= composite_wait(c
);
769 if (NT_STATUS_IS_OK(status
)) {
770 s
= talloc_get_type(c
->private_data
, struct pipe_connect_state
);
771 talloc_steal(mem_ctx
, s
->pipe
);
780 open a rpc connection to a rpc pipe, using the specified
781 binding structure to determine the endpoint and options - sync version
783 NTSTATUS
dcerpc_pipe_connect_b(TALLOC_CTX
*parent_ctx
,
784 struct dcerpc_pipe
**pp
,
785 struct dcerpc_binding
*binding
,
786 const struct dcerpc_interface_table
*table
,
787 struct cli_credentials
*credentials
,
788 struct event_context
*ev
)
790 struct composite_context
*c
;
792 c
= dcerpc_pipe_connect_b_send(parent_ctx
, binding
, table
,
794 return dcerpc_pipe_connect_b_recv(c
, parent_ctx
, pp
);
798 struct pipe_conn_state
{
799 struct dcerpc_pipe
*pipe
;
803 static void continue_pipe_connect_b(struct composite_context
*ctx
);
807 Initiate rpc connection to a rpc pipe, using the specified string
808 binding to determine the endpoint and options.
809 The string is to be parsed to a binding structure first.
811 struct composite_context
* dcerpc_pipe_connect_send(TALLOC_CTX
*parent_ctx
,
813 const struct dcerpc_interface_table
*table
,
814 struct cli_credentials
*credentials
,
815 struct event_context
*ev
)
817 struct composite_context
*c
;
818 struct pipe_conn_state
*s
;
819 struct dcerpc_binding
*b
;
820 struct composite_context
*pipe_conn_req
;
821 struct event_context
*new_ev
= NULL
;
824 new_ev
= event_context_init(parent_ctx
);
825 if (new_ev
== NULL
) return NULL
;
829 /* composite context allocation and setup */
830 c
= composite_create(parent_ctx
, ev
);
835 talloc_steal(c
, new_ev
);
837 s
= talloc_zero(c
, struct pipe_conn_state
);
838 if (composite_nomem(s
, c
)) return c
;
841 /* parse binding string to the structure */
842 c
->status
= dcerpc_parse_binding(c
, binding
, &b
);
843 if (!NT_STATUS_IS_OK(c
->status
)) {
844 DEBUG(0, ("Failed to parse dcerpc binding '%s'\n", binding
));
845 composite_error(c
, c
->status
);
849 DEBUG(3, ("Using binding %s\n", dcerpc_binding_string(c
, b
)));
852 start connecting to a rpc pipe after binding structure
855 pipe_conn_req
= dcerpc_pipe_connect_b_send(c
, b
, table
,
857 composite_continue(c
, pipe_conn_req
, continue_pipe_connect_b
, c
);
863 Stage 2 of pipe_connect: Receive result of actual pipe connect request
864 and say if we're done ok
866 static void continue_pipe_connect_b(struct composite_context
*ctx
)
868 struct composite_context
*c
= talloc_get_type(ctx
->async
.private_data
,
869 struct composite_context
);
870 struct pipe_conn_state
*s
= talloc_get_type(c
->private_data
,
871 struct pipe_conn_state
);
873 c
->status
= dcerpc_pipe_connect_b_recv(ctx
, c
, &s
->pipe
);
874 talloc_steal(s
, s
->pipe
);
875 if (!composite_is_ok(c
)) return;
882 Receive result of pipe connect (using binding string) request
883 and return connected pipe structure.
885 NTSTATUS
dcerpc_pipe_connect_recv(struct composite_context
*c
,
887 struct dcerpc_pipe
**pp
)
890 struct pipe_conn_state
*s
;
892 status
= composite_wait(c
);
893 s
= talloc_get_type(c
->private_data
, struct pipe_conn_state
);
894 *pp
= talloc_steal(mem_ctx
, s
->pipe
);
902 Open a rpc connection to a rpc pipe, using the specified string
903 binding to determine the endpoint and options - sync version
905 NTSTATUS
dcerpc_pipe_connect(TALLOC_CTX
*parent_ctx
,
906 struct dcerpc_pipe
**pp
,
908 const struct dcerpc_interface_table
*table
,
909 struct cli_credentials
*credentials
,
910 struct event_context
*ev
)
912 struct composite_context
*c
;
913 c
= dcerpc_pipe_connect_send(parent_ctx
, binding
,
916 return dcerpc_pipe_connect_recv(c
, parent_ctx
, pp
);
920 struct sec_conn_state
{
921 struct dcerpc_pipe
*pipe
;
922 struct dcerpc_pipe
*pipe2
;
923 struct dcerpc_binding
*binding
;
924 struct smbcli_tree
*tree
;
928 static void continue_open_smb(struct composite_context
*ctx
);
929 static void continue_open_tcp(struct composite_context
*ctx
);
930 static void continue_open_pipe(struct composite_context
*ctx
);
931 static void continue_pipe_open(struct composite_context
*c
);
935 Send request to create a secondary dcerpc connection from a primary
938 struct composite_context
* dcerpc_secondary_connection_send(struct dcerpc_pipe
*p
,
939 struct dcerpc_binding
*b
)
941 struct composite_context
*c
;
942 struct sec_conn_state
*s
;
943 struct composite_context
*pipe_smb_req
;
944 struct composite_context
*pipe_tcp_req
;
945 struct composite_context
*pipe_ncalrpc_req
;
947 /* composite context allocation and setup */
948 c
= composite_create(p
, p
->conn
->event_ctx
);
949 if (c
== NULL
) return NULL
;
951 s
= talloc_zero(c
, struct sec_conn_state
);
952 if (composite_nomem(s
, c
)) return c
;
958 /* initialise second dcerpc pipe based on primary pipe's event context */
959 s
->pipe2
= dcerpc_pipe_init(c
, s
->pipe
->conn
->event_ctx
);
960 if (composite_nomem(s
->pipe2
, c
)) return c
;
962 /* open second dcerpc pipe using the same transport as for primary pipe */
963 switch (s
->pipe
->conn
->transport
.transport
) {
965 /* get smb tree of primary dcerpc pipe opened on smb */
966 s
->tree
= dcerpc_smb_tree(s
->pipe
->conn
);
968 composite_error(c
, NT_STATUS_INVALID_PARAMETER
);
972 pipe_smb_req
= dcerpc_pipe_open_smb_send(s
->pipe2
->conn
, s
->tree
,
973 s
->binding
->endpoint
);
974 composite_continue(c
, pipe_smb_req
, continue_open_smb
, c
);
978 pipe_tcp_req
= dcerpc_pipe_open_tcp_send(s
->pipe2
->conn
,
980 s
->binding
->target_hostname
,
981 atoi(s
->binding
->endpoint
));
982 composite_continue(c
, pipe_tcp_req
, continue_open_tcp
, c
);
986 pipe_ncalrpc_req
= dcerpc_pipe_open_pipe_send(s
->pipe2
->conn
,
987 s
->binding
->endpoint
);
988 composite_continue(c
, pipe_ncalrpc_req
, continue_open_pipe
, c
);
992 /* looks like a transport we don't support */
993 composite_error(c
, NT_STATUS_NOT_SUPPORTED
);
1001 Stage 2 of secondary_connection: Receive result of pipe open request on smb
1003 static void continue_open_smb(struct composite_context
*ctx
)
1005 struct composite_context
*c
= talloc_get_type(ctx
->async
.private_data
,
1006 struct composite_context
);
1008 c
->status
= dcerpc_pipe_open_smb_recv(ctx
);
1009 if (!composite_is_ok(c
)) return;
1011 continue_pipe_open(c
);
1016 Stage 2 of secondary_connection: Receive result of pipe open request on tcp/ip
1018 static void continue_open_tcp(struct composite_context
*ctx
)
1020 struct composite_context
*c
= talloc_get_type(ctx
->async
.private_data
,
1021 struct composite_context
);
1023 c
->status
= dcerpc_pipe_open_tcp_recv(ctx
);
1024 if (!composite_is_ok(c
)) return;
1026 continue_pipe_open(c
);
1031 Stage 2 of secondary_connection: Receive result of pipe open request on ncalrpc
1033 static void continue_open_pipe(struct composite_context
*ctx
)
1035 struct composite_context
*c
= talloc_get_type(ctx
->async
.private_data
,
1036 struct composite_context
);
1038 c
->status
= dcerpc_pipe_open_pipe_recv(ctx
);
1039 if (!composite_is_ok(c
)) return;
1041 continue_pipe_open(c
);
1046 Stage 3 of secondary_connection: Get binding data and flags from primary pipe
1047 and say if we're done ok.
1049 static void continue_pipe_open(struct composite_context
*c
)
1051 struct sec_conn_state
*s
;
1053 s
= talloc_get_type(c
->private_data
, struct sec_conn_state
);
1055 s
->pipe2
->conn
->flags
= s
->pipe
->conn
->flags
;
1056 s
->pipe2
->binding
= s
->binding
;
1057 if (!talloc_reference(s
->pipe2
, s
->binding
)) {
1058 composite_error(c
, NT_STATUS_NO_MEMORY
);
1067 Receive result of secondary rpc connection request and return
1070 NTSTATUS
dcerpc_secondary_connection_recv(struct composite_context
*c
,
1071 struct dcerpc_pipe
**p2
)
1073 NTSTATUS status
= composite_wait(c
);
1074 struct sec_conn_state
*s
;
1076 s
= talloc_get_type(c
->private_data
, struct sec_conn_state
);
1078 if (NT_STATUS_IS_OK(status
)) {
1079 *p2
= talloc_steal(s
->pipe
, s
->pipe2
);
1087 Create a secondary dcerpc connection from a primary connection
1090 If the primary is a SMB connection then the secondary connection
1091 will be on the same SMB connection, but using a new fnum
1093 NTSTATUS
dcerpc_secondary_connection(struct dcerpc_pipe
*p
,
1094 struct dcerpc_pipe
**p2
,
1095 struct dcerpc_binding
*b
)
1097 struct composite_context
*c
;
1099 c
= dcerpc_secondary_connection_send(p
, b
);
1100 return dcerpc_secondary_connection_recv(c
, p2
);