Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : dcerpc connect functions
5 :
6 : Copyright (C) Andrew Tridgell 2003
7 : Copyright (C) Jelmer Vernooij 2004
8 : Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2007
9 : Copyright (C) Rafal Szczesniak 2005
10 :
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 3 of the License, or
14 : (at your option) any later version.
15 :
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.
20 :
21 : You should have received a copy of the GNU General Public License
22 : along with this program. If not, see <http://www.gnu.org/licenses/>.
23 : */
24 :
25 :
26 : #include "includes.h"
27 : #include "libcli/composite/composite.h"
28 : #include "libcli/smb_composite/smb_composite.h"
29 : #include "lib/events/events.h"
30 : #include "libcli/smb2/smb2.h"
31 : #include "libcli/smb2/smb2_calls.h"
32 : #include "libcli/smb/smbXcli_base.h"
33 : #include "librpc/rpc/dcerpc.h"
34 : #include "librpc/rpc/dcerpc_proto.h"
35 : #include "auth/credentials/credentials.h"
36 : #include "param/param.h"
37 : #include "libcli/resolve/resolve.h"
38 : #include "libcli/http/http.h"
39 : #include "lib/util/util_net.h"
40 :
41 : #undef strcasecmp
42 :
43 : struct dcerpc_pipe_connect {
44 : struct dcecli_connection *conn;
45 : struct dcerpc_binding *binding;
46 : const struct ndr_interface_table *interface;
47 : struct cli_credentials *creds;
48 : struct resolve_context *resolve_ctx;
49 : struct {
50 : const char *dir;
51 : } ncalrpc;
52 : struct {
53 : struct smbXcli_conn *conn;
54 : struct smbXcli_session *session;
55 : struct smbXcli_tcon *tcon;
56 : const char *pipe_name;
57 : } smb;
58 : };
59 :
60 : struct pipe_np_smb_state {
61 : struct smb_composite_connect conn;
62 : struct dcerpc_pipe_connect io;
63 : };
64 :
65 :
66 : /*
67 : Stage 3 of ncacn_np_smb: Named pipe opened (or not)
68 : */
69 3630 : static void continue_pipe_open_smb(struct composite_context *ctx)
70 : {
71 3630 : struct composite_context *c = talloc_get_type(ctx->async.private_data,
72 : struct composite_context);
73 :
74 : /* receive result of named pipe open request on smb */
75 3630 : c->status = dcerpc_pipe_open_smb_recv(ctx);
76 3630 : if (!composite_is_ok(c)) return;
77 :
78 3472 : composite_done(c);
79 : }
80 :
81 : static void continue_smb_open(struct composite_context *c);
82 : static void continue_smb2_connect(struct tevent_req *subreq);
83 : static void continue_smbXcli_connect(struct tevent_req *subreq);
84 :
85 : /*
86 : Stage 2 of ncacn_np_smb: Open a named pipe after successful smb connection
87 : */
88 0 : static void continue_smb_connect(struct composite_context *ctx)
89 : {
90 0 : struct composite_context *c = talloc_get_type(ctx->async.private_data,
91 : struct composite_context);
92 0 : struct pipe_np_smb_state *s = talloc_get_type(c->private_data,
93 : struct pipe_np_smb_state);
94 : struct smbcli_tree *t;
95 :
96 : /* receive result of smb connect request */
97 0 : c->status = smb_composite_connect_recv(ctx, s->io.conn);
98 0 : if (!composite_is_ok(c)) return;
99 :
100 0 : t = s->conn.out.tree;
101 :
102 : /* prepare named pipe open parameters */
103 0 : s->io.smb.conn = t->session->transport->conn;
104 0 : s->io.smb.session = t->session->smbXcli;
105 0 : s->io.smb.tcon = t->smbXcli;
106 0 : smb1cli_tcon_set_id(s->io.smb.tcon, t->tid);
107 0 : s->io.smb.pipe_name = dcerpc_binding_get_string_option(s->io.binding,
108 : "endpoint");
109 :
110 0 : continue_smb_open(c);
111 : }
112 :
113 3630 : static void continue_smb_open(struct composite_context *c)
114 : {
115 3630 : struct pipe_np_smb_state *s = talloc_get_type(c->private_data,
116 : struct pipe_np_smb_state);
117 : struct composite_context *open_ctx;
118 :
119 : /* send named pipe open request */
120 3630 : open_ctx = dcerpc_pipe_open_smb_send(s->io.conn,
121 : s->io.smb.conn,
122 : s->io.smb.session,
123 : s->io.smb.tcon,
124 : DCERPC_REQUEST_TIMEOUT * 1000,
125 : s->io.smb.pipe_name);
126 3630 : if (composite_nomem(open_ctx, c)) return;
127 :
128 3630 : composite_continue(c, open_ctx, continue_pipe_open_smb, c);
129 : }
130 :
131 :
132 : /*
133 : Initiate async open of a rpc connection to a rpc pipe on SMB using
134 : the binding structure to determine the endpoint and options
135 : */
136 3650 : static struct composite_context *dcerpc_pipe_connect_ncacn_np_smb_send(TALLOC_CTX *mem_ctx, struct dcerpc_pipe_connect *io, struct loadparm_context *lp_ctx)
137 : {
138 : struct composite_context *c;
139 : struct pipe_np_smb_state *s;
140 3650 : struct tevent_req *subreq = NULL;
141 : struct smb_composite_connect *conn;
142 : uint32_t flags;
143 3650 : const char *target_hostname = NULL;
144 3650 : const char *dest_address = NULL;
145 3650 : const char *calling_name = NULL;
146 :
147 : /* composite context allocation and setup */
148 3650 : c = composite_create(mem_ctx, io->conn->event_ctx);
149 3650 : if (c == NULL) return NULL;
150 :
151 3650 : s = talloc_zero(c, struct pipe_np_smb_state);
152 3650 : if (composite_nomem(s, c)) return c;
153 3650 : c->private_data = s;
154 :
155 3650 : s->io = *io;
156 3650 : conn = &s->conn;
157 :
158 3650 : if (smbXcli_conn_is_connected(s->io.smb.conn)) {
159 0 : continue_smb_open(c);
160 0 : return c;
161 : }
162 :
163 3650 : if (s->io.creds == NULL) {
164 0 : composite_error(c, NT_STATUS_INVALID_PARAMETER_MIX);
165 0 : return c;
166 : }
167 :
168 : /* prepare smb connection parameters: we're connecting to IPC$ share on
169 : remote rpc server */
170 3650 : target_hostname = dcerpc_binding_get_string_option(s->io.binding, "target_hostname");
171 3650 : conn->in.dest_host = dcerpc_binding_get_string_option(s->io.binding, "host");
172 3650 : conn->in.dest_ports = lpcfg_smb_ports(lp_ctx);
173 3650 : conn->in.called_name = target_hostname;
174 3650 : if (conn->in.called_name == NULL) {
175 0 : conn->in.called_name = "*SMBSERVER";
176 : }
177 3650 : conn->in.socket_options = lpcfg_socket_options(lp_ctx);
178 3650 : conn->in.service = "IPC$";
179 3650 : conn->in.service_type = NULL;
180 3650 : conn->in.workgroup = lpcfg_workgroup(lp_ctx);
181 3650 : conn->in.gensec_settings = lpcfg_gensec_settings(conn, lp_ctx);
182 :
183 3650 : lpcfg_smbcli_options(lp_ctx, &conn->in.options);
184 3650 : lpcfg_smbcli_session_options(lp_ctx, &conn->in.session_options);
185 :
186 : /*
187 : * provide proper credentials - user supplied, but allow a
188 : * fallback to anonymous if this is an schannel connection
189 : * (might be NT4 not allowing machine logins at session
190 : * setup) or if asked to do so by the caller (perhaps a SAMR password change?)
191 : */
192 3650 : s->conn.in.credentials = s->io.creds;
193 3650 : flags = dcerpc_binding_get_flags(s->io.binding);
194 3650 : if (flags & (DCERPC_SCHANNEL|DCERPC_ANON_FALLBACK)) {
195 364 : conn->in.fallback_to_anonymous = true;
196 : } else {
197 3286 : conn->in.fallback_to_anonymous = false;
198 : }
199 :
200 3650 : conn->in.options.min_protocol = lpcfg_client_ipc_min_protocol(lp_ctx);
201 3650 : conn->in.options.max_protocol = lpcfg_client_ipc_max_protocol(lp_ctx);
202 3650 : if ((flags & DCERPC_SMB1) && (flags & DCERPC_SMB2)) {
203 : /* auto */
204 3650 : } else if (flags & DCERPC_SMB2) {
205 31 : if (conn->in.options.min_protocol < PROTOCOL_SMB2_02) {
206 31 : conn->in.options.min_protocol = PROTOCOL_SMB2_02;
207 : }
208 31 : if (conn->in.options.max_protocol < PROTOCOL_SMB2_02) {
209 0 : conn->in.options.max_protocol = PROTOCOL_LATEST;
210 : }
211 3619 : } else if (flags & DCERPC_SMB1) {
212 0 : conn->in.options.min_protocol = PROTOCOL_NT1;
213 0 : conn->in.options.max_protocol = PROTOCOL_NT1;
214 : } else {
215 : /* auto */
216 : }
217 :
218 3650 : conn->in.options.signing = lpcfg_client_ipc_signing(lp_ctx);
219 :
220 3650 : if (s->conn.in.credentials != NULL) {
221 3650 : calling_name = cli_credentials_get_workstation(s->conn.in.credentials);
222 : }
223 3650 : if (calling_name == NULL) {
224 9 : calling_name = "SMBCLIENT";
225 : }
226 :
227 3650 : if (target_hostname == NULL) {
228 0 : target_hostname = conn->in.dest_host;
229 : }
230 :
231 3650 : if (conn->in.dest_host != NULL && is_ipaddress(conn->in.dest_host)) {
232 110 : dest_address = conn->in.dest_host;
233 : }
234 :
235 6376 : subreq = smb_connect_nego_send(s,
236 : c->event_ctx,
237 : s->io.resolve_ctx,
238 3650 : &conn->in.options,
239 : conn->in.socket_options,
240 : conn->in.dest_host,
241 : dest_address,
242 : conn->in.dest_ports,
243 : target_hostname,
244 : conn->in.called_name,
245 : calling_name);
246 3650 : if (composite_nomem(subreq, c)) return c;
247 3650 : tevent_req_set_callback(subreq,
248 : continue_smbXcli_connect,
249 : c);
250 :
251 3650 : return c;
252 : }
253 :
254 3650 : static void continue_smbXcli_connect(struct tevent_req *subreq)
255 : {
256 2726 : struct composite_context *c =
257 3650 : tevent_req_callback_data(subreq,
258 : struct composite_context);
259 2726 : struct pipe_np_smb_state *s =
260 3650 : talloc_get_type_abort(c->private_data,
261 : struct pipe_np_smb_state);
262 3650 : struct smb_composite_connect *conn = &s->conn;
263 3650 : struct composite_context *creq = NULL;
264 : enum protocol_types protocol;
265 :
266 3650 : c->status = smb_connect_nego_recv(subreq, s,
267 : &conn->in.existing_conn);
268 3650 : TALLOC_FREE(subreq);
269 3650 : if (!composite_is_ok(c)) return;
270 :
271 3649 : protocol = smbXcli_conn_protocol(conn->in.existing_conn);
272 3649 : if (protocol >= PROTOCOL_SMB2_02) {
273 : /*
274 : * continue with smb2 session setup/tree connect
275 : * on the established connection.
276 : */
277 9099 : subreq = smb2_connect_send(s, c->event_ctx,
278 : conn->in.dest_host,
279 : conn->in.dest_ports,
280 : conn->in.service,
281 : s->io.resolve_ctx,
282 : conn->in.credentials,
283 3649 : conn->in.fallback_to_anonymous,
284 : &conn->in.existing_conn,
285 : 0, /* previous_session_id */
286 3649 : &conn->in.options,
287 : conn->in.socket_options,
288 : conn->in.gensec_settings);
289 3649 : if (composite_nomem(subreq, c)) return;
290 3649 : tevent_req_set_callback(subreq, continue_smb2_connect, c);
291 3649 : return;
292 : }
293 :
294 : /*
295 : * continue with smb1 session setup/tree connect
296 : * on the established connection.
297 : */
298 0 : creq = smb_composite_connect_send(conn, s->io.conn,
299 : s->io.resolve_ctx,
300 : c->event_ctx);
301 0 : if (composite_nomem(creq, c)) return;
302 :
303 0 : composite_continue(c, creq, continue_smb_connect, c);
304 0 : return;
305 : }
306 :
307 :
308 : /*
309 : Receive result of a rpc connection to a rpc pipe on SMB
310 : */
311 3650 : static NTSTATUS dcerpc_pipe_connect_ncacn_np_smb_recv(struct composite_context *c)
312 : {
313 3650 : NTSTATUS status = composite_wait(c);
314 :
315 3650 : talloc_free(c);
316 3650 : return status;
317 : }
318 :
319 : /*
320 : Stage 2 of ncacn_np_smb2: Open a named pipe after successful smb2 connection
321 : */
322 3649 : static void continue_smb2_connect(struct tevent_req *subreq)
323 : {
324 2725 : struct composite_context *c =
325 3649 : tevent_req_callback_data(subreq,
326 : struct composite_context);
327 3649 : struct pipe_np_smb_state *s = talloc_get_type(c->private_data,
328 : struct pipe_np_smb_state);
329 : struct smb2_tree *t;
330 :
331 : /* receive result of smb2 connect request */
332 3649 : c->status = smb2_connect_recv(subreq, s->io.conn, &t);
333 3649 : TALLOC_FREE(subreq);
334 3649 : if (!composite_is_ok(c)) return;
335 :
336 3630 : s->io.smb.conn = t->session->transport->conn;
337 3630 : s->io.smb.session = t->session->smbXcli;
338 3630 : s->io.smb.tcon = t->smbXcli;
339 3630 : s->io.smb.pipe_name = dcerpc_binding_get_string_option(s->io.binding,
340 : "endpoint");
341 :
342 3630 : continue_smb_open(c);
343 : }
344 :
345 :
346 : struct pipe_ip_tcp_state {
347 : struct dcerpc_pipe_connect io;
348 : const char *localaddr;
349 : const char *host;
350 : const char *target_hostname;
351 : uint32_t port;
352 : };
353 :
354 :
355 : /*
356 : Stage 2 of ncacn_ip_tcp: rpc pipe opened (or not)
357 : */
358 13844 : static void continue_pipe_open_ncacn_ip_tcp(struct composite_context *ctx)
359 : {
360 13844 : struct composite_context *c = talloc_get_type(ctx->async.private_data,
361 : struct composite_context);
362 13844 : struct pipe_ip_tcp_state *s = talloc_get_type(c->private_data,
363 : struct pipe_ip_tcp_state);
364 13844 : char *localaddr = NULL;
365 13844 : char *remoteaddr = NULL;
366 :
367 : /* receive result of named pipe open request on tcp/ip */
368 13844 : c->status = dcerpc_pipe_open_tcp_recv(ctx, s, &localaddr, &remoteaddr);
369 18412 : if (!composite_is_ok(c)) return;
370 :
371 9040 : c->status = dcerpc_binding_set_string_option(s->io.binding,
372 : "localaddress",
373 : localaddr);
374 9040 : if (!composite_is_ok(c)) return;
375 :
376 9040 : c->status = dcerpc_binding_set_string_option(s->io.binding,
377 : "host",
378 : remoteaddr);
379 9040 : if (!composite_is_ok(c)) return;
380 :
381 9040 : composite_done(c);
382 : }
383 :
384 :
385 : /*
386 : Initiate async open of a rpc connection to a rpc pipe on TCP/IP using
387 : the binding structure to determine the endpoint and options
388 : */
389 13846 : static struct composite_context* dcerpc_pipe_connect_ncacn_ip_tcp_send(TALLOC_CTX *mem_ctx,
390 : struct dcerpc_pipe_connect *io)
391 : {
392 : struct composite_context *c;
393 : struct pipe_ip_tcp_state *s;
394 : struct composite_context *pipe_req;
395 : const char *endpoint;
396 :
397 : /* composite context allocation and setup */
398 13846 : c = composite_create(mem_ctx, io->conn->event_ctx);
399 13846 : if (c == NULL) return NULL;
400 :
401 13846 : s = talloc_zero(c, struct pipe_ip_tcp_state);
402 13846 : if (composite_nomem(s, c)) return c;
403 13846 : c->private_data = s;
404 :
405 : /* store input parameters in state structure */
406 13846 : s->io = *io;
407 13846 : s->localaddr = dcerpc_binding_get_string_option(io->binding,
408 : "localaddress");
409 13846 : s->host = dcerpc_binding_get_string_option(io->binding, "host");
410 13846 : s->target_hostname = dcerpc_binding_get_string_option(io->binding,
411 : "target_hostname");
412 13846 : endpoint = dcerpc_binding_get_string_option(io->binding, "endpoint");
413 : /* port number is a binding endpoint here */
414 13846 : if (endpoint != NULL) {
415 13846 : s->port = atoi(endpoint);
416 : }
417 :
418 13846 : if (s->port == 0) {
419 0 : composite_error(c, NT_STATUS_INVALID_PARAMETER_MIX);
420 0 : return c;
421 : }
422 :
423 : /* send pipe open request on tcp/ip */
424 13846 : pipe_req = dcerpc_pipe_open_tcp_send(s->io.conn, s->localaddr, s->host, s->target_hostname,
425 : s->port, io->resolve_ctx);
426 13846 : composite_continue(c, pipe_req, continue_pipe_open_ncacn_ip_tcp, c);
427 13846 : return c;
428 : }
429 :
430 :
431 : /*
432 : Receive result of a rpc connection to a rpc pipe on TCP/IP
433 : */
434 13844 : static NTSTATUS dcerpc_pipe_connect_ncacn_ip_tcp_recv(struct composite_context *c)
435 : {
436 13844 : NTSTATUS status = composite_wait(c);
437 :
438 13844 : talloc_free(c);
439 13844 : return status;
440 : }
441 :
442 :
443 : struct pipe_http_state {
444 : struct dcerpc_pipe_connect io;
445 : const char *localaddr;
446 : const char *target_hostname;
447 : const char *rpc_server;
448 : uint32_t rpc_server_port;
449 : char *rpc_proxy;
450 : uint32_t rpc_proxy_port;
451 : char *http_proxy;
452 : uint32_t http_proxy_port;
453 : bool use_tls;
454 : bool use_proxy;
455 : enum http_auth_method http_auth;
456 : struct loadparm_context *lp_ctx;
457 : };
458 :
459 : /*
460 : Stage 2 of ncacn_http: rpc pipe opened (or not)
461 : */
462 0 : static void continue_pipe_open_ncacn_http(struct tevent_req *subreq)
463 : {
464 0 : struct composite_context *c = NULL;
465 0 : struct pipe_http_state *s = NULL;
466 0 : struct tstream_context *stream = NULL;
467 0 : struct tevent_queue *queue = NULL;
468 :
469 0 : c = tevent_req_callback_data(subreq, struct composite_context);
470 0 : s = talloc_get_type(c->private_data, struct pipe_http_state);
471 :
472 : /* receive result of RoH connect request */
473 0 : c->status = dcerpc_pipe_open_roh_recv(subreq, s->io.conn,
474 : &stream, &queue);
475 0 : TALLOC_FREE(subreq);
476 0 : if (!composite_is_ok(c)) return;
477 :
478 0 : s->io.conn->transport.transport = NCACN_HTTP;
479 0 : s->io.conn->transport.stream = stream;
480 0 : s->io.conn->transport.write_queue = queue;
481 0 : s->io.conn->transport.pending_reads = 0;
482 0 : s->io.conn->server_name = strupper_talloc(s->io.conn,
483 : s->target_hostname);
484 :
485 0 : composite_done(c);
486 : }
487 :
488 : /*
489 : Initiate async open of a rpc connection to a rpc pipe using HTTP transport,
490 : and using the binding structure to determine the endpoint and options
491 : */
492 0 : static struct composite_context* dcerpc_pipe_connect_ncacn_http_send(
493 : TALLOC_CTX *mem_ctx, struct dcerpc_pipe_connect *io,
494 : struct loadparm_context *lp_ctx)
495 : {
496 : struct composite_context *c;
497 : struct pipe_http_state *s;
498 : struct tevent_req *subreq;
499 : const char *endpoint;
500 : const char *use_proxy;
501 : char *proxy;
502 : char *port;
503 : const char *opt;
504 :
505 : /* composite context allocation and setup */
506 0 : c = composite_create(mem_ctx, io->conn->event_ctx);
507 0 : if (c == NULL) return NULL;
508 :
509 0 : s = talloc_zero(c, struct pipe_http_state);
510 0 : if (composite_nomem(s, c)) return c;
511 0 : c->private_data = s;
512 :
513 : /* store input parameters in state structure */
514 0 : s->lp_ctx = lp_ctx;
515 0 : s->io = *io;
516 0 : s->localaddr = dcerpc_binding_get_string_option(io->binding,
517 : "localaddress");
518 : /* RPC server and port (the endpoint) */
519 0 : s->rpc_server = dcerpc_binding_get_string_option(io->binding, "host");
520 0 : s->target_hostname = dcerpc_binding_get_string_option(io->binding,
521 : "target_hostname");
522 0 : endpoint = dcerpc_binding_get_string_option(io->binding, "endpoint");
523 0 : if (endpoint == NULL) {
524 0 : composite_error(c, NT_STATUS_INVALID_PARAMETER_MIX);
525 0 : return c;
526 : }
527 0 : s->rpc_server_port = atoi(endpoint);
528 0 : if (s->rpc_server_port == 0) {
529 0 : composite_error(c, NT_STATUS_INVALID_PARAMETER_MIX);
530 0 : return c;
531 : }
532 :
533 : /* Use TLS */
534 0 : opt = dcerpc_binding_get_string_option(io->binding, "HttpUseTls");
535 0 : if (opt) {
536 0 : if (strcasecmp(opt, "true") == 0) {
537 0 : s->use_tls = true;
538 0 : } else if (strcasecmp(opt, "false") == 0) {
539 0 : s->use_tls = false;
540 : } else {
541 0 : composite_error(c, NT_STATUS_INVALID_PARAMETER_MIX);
542 0 : return c;
543 : }
544 : } else {
545 0 : s->use_tls = true;
546 : }
547 :
548 : /* RPC Proxy */
549 0 : proxy = port = talloc_strdup(s, dcerpc_binding_get_string_option(
550 0 : io->binding, "RpcProxy"));
551 0 : s->rpc_proxy = strsep(&port, ":");
552 0 : if (proxy && port) {
553 0 : s->rpc_proxy_port = atoi(port);
554 : } else {
555 0 : s->rpc_proxy_port = s->use_tls ? 443 : 80;
556 : }
557 0 : if (s->rpc_proxy == NULL) {
558 0 : s->rpc_proxy = talloc_strdup(s, s->rpc_server);
559 0 : if (composite_nomem(s->rpc_proxy, c)) return c;
560 : }
561 :
562 : /* HTTP Proxy */
563 0 : proxy = port = talloc_strdup(s, dcerpc_binding_get_string_option(
564 0 : io->binding, "HttpProxy"));
565 0 : s->http_proxy = strsep(&port, ":");
566 0 : if (proxy && port) {
567 0 : s->http_proxy_port = atoi(port);
568 : } else {
569 0 : s->http_proxy_port = s->use_tls ? 443 : 80;
570 : }
571 :
572 : /* Use local proxy */
573 0 : use_proxy = dcerpc_binding_get_string_option(io->binding,
574 : "HttpConnectOption");
575 0 : if (use_proxy && strcasecmp(use_proxy, "UseHttpProxy")) {
576 0 : s->use_proxy = true;
577 : }
578 :
579 : /* If use local proxy set, the http proxy should be provided */
580 0 : if (s->use_proxy && !s->http_proxy) {
581 0 : composite_error(c, NT_STATUS_INVALID_PARAMETER_MIX);
582 0 : return c;
583 : }
584 :
585 : /* Check which HTTP authentication method to use */
586 0 : opt = dcerpc_binding_get_string_option(io->binding, "HttpAuthOption");
587 0 : if (opt) {
588 0 : if (strcasecmp(opt, "basic") == 0) {
589 0 : s->http_auth = HTTP_AUTH_BASIC;
590 0 : } else if (strcasecmp(opt, "ntlm") == 0) {
591 0 : s->http_auth = HTTP_AUTH_NTLM;
592 0 : } else if (strcasecmp(opt, "negotiate") == 0) {
593 0 : s->http_auth = HTTP_AUTH_NEGOTIATE;
594 : } else {
595 0 : composite_error(c, NT_STATUS_INVALID_PARAMETER_MIX);
596 0 : return c;
597 : }
598 : } else {
599 0 : s->http_auth = HTTP_AUTH_NTLM;
600 : }
601 :
602 0 : subreq = dcerpc_pipe_open_roh_send(s->io.conn, s->localaddr,
603 : s->rpc_server, s->rpc_server_port,
604 0 : s->rpc_proxy, s->rpc_proxy_port,
605 0 : s->http_proxy, s->http_proxy_port,
606 0 : s->use_tls, s->use_proxy,
607 : s->io.creds, io->resolve_ctx,
608 0 : s->lp_ctx, s->http_auth);
609 0 : if (composite_nomem(subreq, c)) return c;
610 :
611 0 : tevent_req_set_callback(subreq, continue_pipe_open_ncacn_http, c);
612 0 : return c;
613 : }
614 :
615 0 : static NTSTATUS dcerpc_pipe_connect_ncacn_http_recv(struct composite_context *c)
616 : {
617 0 : return composite_wait_free(c);
618 : }
619 :
620 :
621 : struct pipe_unix_state {
622 : struct dcerpc_pipe_connect io;
623 : const char *path;
624 : };
625 :
626 :
627 : /*
628 : Stage 2 of ncacn_unix: rpc pipe opened (or not)
629 : */
630 0 : static void continue_pipe_open_ncacn_unix_stream(struct composite_context *ctx)
631 : {
632 0 : struct composite_context *c = talloc_get_type(ctx->async.private_data,
633 : struct composite_context);
634 :
635 : /* receive result of pipe open request on unix socket */
636 0 : c->status = dcerpc_pipe_open_unix_stream_recv(ctx);
637 0 : if (!composite_is_ok(c)) return;
638 :
639 0 : composite_done(c);
640 : }
641 :
642 :
643 : /*
644 : Initiate async open of a rpc connection to a rpc pipe on unix socket using
645 : the binding structure to determine the endpoint and options
646 : */
647 0 : static struct composite_context* dcerpc_pipe_connect_ncacn_unix_stream_send(TALLOC_CTX *mem_ctx,
648 : struct dcerpc_pipe_connect *io)
649 : {
650 : struct composite_context *c;
651 : struct pipe_unix_state *s;
652 : struct composite_context *pipe_req;
653 :
654 : /* composite context allocation and setup */
655 0 : c = composite_create(mem_ctx, io->conn->event_ctx);
656 0 : if (c == NULL) return NULL;
657 :
658 0 : s = talloc_zero(c, struct pipe_unix_state);
659 0 : if (composite_nomem(s, c)) return c;
660 0 : c->private_data = s;
661 :
662 : /* prepare pipe open parameters and store them in state structure
663 : also, verify whether biding endpoint is not null */
664 0 : s->io = *io;
665 :
666 0 : s->path = dcerpc_binding_get_string_option(io->binding, "endpoint");
667 0 : if (s->path == NULL) {
668 0 : composite_error(c, NT_STATUS_INVALID_PARAMETER_MIX);
669 0 : return c;
670 : }
671 :
672 : /* send pipe open request on unix socket */
673 0 : pipe_req = dcerpc_pipe_open_unix_stream_send(s->io.conn, s->path);
674 0 : composite_continue(c, pipe_req, continue_pipe_open_ncacn_unix_stream, c);
675 0 : return c;
676 : }
677 :
678 :
679 : /*
680 : Receive result of a rpc connection to a pipe on unix socket
681 : */
682 0 : static NTSTATUS dcerpc_pipe_connect_ncacn_unix_stream_recv(struct composite_context *c)
683 : {
684 0 : NTSTATUS status = composite_wait(c);
685 :
686 0 : talloc_free(c);
687 0 : return status;
688 : }
689 :
690 :
691 : struct pipe_ncalrpc_state {
692 : struct dcerpc_pipe_connect io;
693 : };
694 :
695 : static NTSTATUS dcerpc_pipe_connect_ncalrpc_recv(struct composite_context *c);
696 :
697 : /*
698 : Stage 2 of ncalrpc: rpc pipe opened (or not)
699 : */
700 1280 : static void continue_pipe_open_ncalrpc(struct composite_context *ctx)
701 : {
702 1280 : struct composite_context *c = talloc_get_type(ctx->async.private_data,
703 : struct composite_context);
704 :
705 : /* receive result of pipe open request on ncalrpc */
706 1280 : c->status = dcerpc_pipe_connect_ncalrpc_recv(ctx);
707 1280 : if (!composite_is_ok(c)) return;
708 :
709 1280 : composite_done(c);
710 : }
711 :
712 :
713 : /*
714 : Initiate async open of a rpc connection request on NCALRPC using
715 : the binding structure to determine the endpoint and options
716 : */
717 1280 : static struct composite_context* dcerpc_pipe_connect_ncalrpc_send(TALLOC_CTX *mem_ctx,
718 : struct dcerpc_pipe_connect *io)
719 : {
720 : struct composite_context *c;
721 : struct pipe_ncalrpc_state *s;
722 : struct composite_context *pipe_req;
723 : const char *endpoint;
724 :
725 : /* composite context allocation and setup */
726 1280 : c = composite_create(mem_ctx, io->conn->event_ctx);
727 1280 : if (c == NULL) return NULL;
728 :
729 1280 : s = talloc_zero(c, struct pipe_ncalrpc_state);
730 1280 : if (composite_nomem(s, c)) return c;
731 1280 : c->private_data = s;
732 :
733 : /* store input parameters in state structure */
734 1280 : s->io = *io;
735 :
736 1280 : endpoint = dcerpc_binding_get_string_option(io->binding, "endpoint");
737 1280 : if (endpoint == NULL) {
738 0 : composite_error(c, NT_STATUS_INVALID_PARAMETER_MIX);
739 0 : return c;
740 : }
741 :
742 : /* send pipe open request */
743 1280 : pipe_req = dcerpc_pipe_open_pipe_send(s->io.conn,
744 : s->io.ncalrpc.dir,
745 : endpoint);
746 1280 : composite_continue(c, pipe_req, continue_pipe_open_ncalrpc, c);
747 1280 : return c;
748 : }
749 :
750 :
751 : /*
752 : Receive result of a rpc connection to a rpc pipe on NCALRPC
753 : */
754 2560 : static NTSTATUS dcerpc_pipe_connect_ncalrpc_recv(struct composite_context *c)
755 : {
756 2560 : NTSTATUS status = composite_wait(c);
757 :
758 2560 : talloc_free(c);
759 2560 : return status;
760 : }
761 :
762 :
763 : struct pipe_connect_state {
764 : struct dcerpc_pipe *pipe;
765 : struct dcerpc_binding *binding;
766 : const struct ndr_interface_table *table;
767 : struct cli_credentials *credentials;
768 : struct loadparm_context *lp_ctx;
769 : };
770 :
771 :
772 : static void continue_map_binding(struct composite_context *ctx);
773 : static void continue_connect(struct composite_context *c, struct pipe_connect_state *s);
774 : static void continue_pipe_connect_ncacn_np_smb(struct composite_context *ctx);
775 : static void continue_pipe_connect_ncacn_ip_tcp(struct composite_context *ctx);
776 : static void continue_pipe_connect_ncacn_http(struct composite_context *ctx);
777 : static void continue_pipe_connect_ncacn_unix(struct composite_context *ctx);
778 : static void continue_pipe_connect_ncalrpc(struct composite_context *ctx);
779 : static void continue_pipe_connect(struct composite_context *c, struct pipe_connect_state *s);
780 : static void continue_pipe_auth(struct composite_context *ctx);
781 :
782 :
783 : /*
784 : Stage 2 of pipe_connect_b: Receive result of endpoint mapping
785 : */
786 22776 : static void continue_map_binding(struct composite_context *ctx)
787 : {
788 22776 : struct composite_context *c = talloc_get_type(ctx->async.private_data,
789 : struct composite_context);
790 22776 : struct pipe_connect_state *s = talloc_get_type(c->private_data,
791 : struct pipe_connect_state);
792 : const char *endpoint;
793 :
794 22776 : c->status = dcerpc_epm_map_binding_recv(ctx);
795 22776 : if (!composite_is_ok(c)) return;
796 :
797 17972 : endpoint = dcerpc_binding_get_string_option(s->binding, "endpoint");
798 17972 : DEBUG(4,("Mapped to DCERPC endpoint %s\n", endpoint));
799 :
800 17972 : continue_connect(c, s);
801 : }
802 :
803 :
804 : /*
805 : Stage 2 of pipe_connect_b: Continue connection after endpoint is known
806 : */
807 18776 : static void continue_connect(struct composite_context *c, struct pipe_connect_state *s)
808 : {
809 : struct dcerpc_pipe_connect pc;
810 :
811 : /* potential exits to another stage by sending an async request */
812 : struct composite_context *ncacn_np_smb_req;
813 : struct composite_context *ncacn_ip_tcp_req;
814 : struct composite_context *ncacn_http_req;
815 : struct composite_context *ncacn_unix_req;
816 : struct composite_context *ncalrpc_req;
817 : enum dcerpc_transport_t transport;
818 :
819 : /* dcerpc pipe connect input parameters */
820 18776 : ZERO_STRUCT(pc);
821 18776 : pc.conn = s->pipe->conn;
822 18776 : pc.binding = s->binding;
823 18776 : pc.interface = s->table;
824 18776 : pc.creds = s->credentials;
825 18776 : pc.resolve_ctx = lpcfg_resolve_context(s->lp_ctx);
826 :
827 18776 : transport = dcerpc_binding_get_transport(s->binding);
828 :
829 : /* connect dcerpc pipe depending on required transport */
830 18776 : switch (transport) {
831 3650 : case NCACN_NP:
832 : /*
833 : * SMB1/2/3...
834 : */
835 3650 : ncacn_np_smb_req = dcerpc_pipe_connect_ncacn_np_smb_send(c, &pc, s->lp_ctx);
836 3650 : composite_continue(c, ncacn_np_smb_req, continue_pipe_connect_ncacn_np_smb, c);
837 4818 : return;
838 :
839 13846 : case NCACN_IP_TCP:
840 13846 : ncacn_ip_tcp_req = dcerpc_pipe_connect_ncacn_ip_tcp_send(c, &pc);
841 13846 : composite_continue(c, ncacn_ip_tcp_req, continue_pipe_connect_ncacn_ip_tcp, c);
842 13846 : return;
843 :
844 0 : case NCACN_HTTP:
845 0 : ncacn_http_req = dcerpc_pipe_connect_ncacn_http_send(c, &pc, s->lp_ctx);
846 0 : composite_continue(c, ncacn_http_req, continue_pipe_connect_ncacn_http, c);
847 0 : return;
848 :
849 0 : case NCACN_UNIX_STREAM:
850 0 : ncacn_unix_req = dcerpc_pipe_connect_ncacn_unix_stream_send(c, &pc);
851 0 : composite_continue(c, ncacn_unix_req, continue_pipe_connect_ncacn_unix, c);
852 0 : return;
853 :
854 1280 : case NCALRPC:
855 1280 : pc.ncalrpc.dir = lpcfg_ncalrpc_dir(s->lp_ctx);
856 1280 : c->status = dcerpc_binding_set_string_option(s->binding, "ncalrpc_dir",
857 : pc.ncalrpc.dir);
858 1280 : if (!composite_is_ok(c)) return;
859 1280 : ncalrpc_req = dcerpc_pipe_connect_ncalrpc_send(c, &pc);
860 1280 : composite_continue(c, ncalrpc_req, continue_pipe_connect_ncalrpc, c);
861 1280 : return;
862 :
863 0 : default:
864 : /* looks like a transport we don't support now */
865 0 : composite_error(c, NT_STATUS_NOT_SUPPORTED);
866 : }
867 : }
868 :
869 :
870 : /*
871 : Stage 3 of pipe_connect_b: Receive result of pipe connect request on
872 : named pipe on smb
873 : */
874 3650 : static void continue_pipe_connect_ncacn_np_smb(struct composite_context *ctx)
875 : {
876 3650 : struct composite_context *c = talloc_get_type(ctx->async.private_data,
877 : struct composite_context);
878 3650 : struct pipe_connect_state *s = talloc_get_type(c->private_data,
879 : struct pipe_connect_state);
880 :
881 3650 : c->status = dcerpc_pipe_connect_ncacn_np_smb_recv(ctx);
882 3650 : if (!composite_is_ok(c)) return;
883 :
884 3472 : continue_pipe_connect(c, s);
885 : }
886 :
887 :
888 : /*
889 : Stage 3 of pipe_connect_b: Receive result of pipe connect request on tcp/ip
890 : */
891 13844 : static void continue_pipe_connect_ncacn_ip_tcp(struct composite_context *ctx)
892 : {
893 13844 : struct composite_context *c = talloc_get_type(ctx->async.private_data,
894 : struct composite_context);
895 13844 : struct pipe_connect_state *s = talloc_get_type(c->private_data,
896 : struct pipe_connect_state);
897 :
898 13844 : c->status = dcerpc_pipe_connect_ncacn_ip_tcp_recv(ctx);
899 13844 : if (!composite_is_ok(c)) return;
900 :
901 9040 : continue_pipe_connect(c, s);
902 : }
903 :
904 :
905 : /*
906 : Stage 3 of pipe_connect_b: Receive result of pipe connect request on http
907 : */
908 0 : static void continue_pipe_connect_ncacn_http(struct composite_context *ctx)
909 : {
910 0 : struct composite_context *c = talloc_get_type(ctx->async.private_data,
911 : struct composite_context);
912 0 : struct pipe_connect_state *s = talloc_get_type(c->private_data,
913 : struct pipe_connect_state);
914 :
915 0 : c->status = dcerpc_pipe_connect_ncacn_http_recv(ctx);
916 0 : if (!composite_is_ok(c)) return;
917 :
918 0 : continue_pipe_connect(c, s);
919 : }
920 :
921 :
922 : /*
923 : Stage 3 of pipe_connect_b: Receive result of pipe connect request on unix socket
924 : */
925 0 : static void continue_pipe_connect_ncacn_unix(struct composite_context *ctx)
926 : {
927 0 : struct composite_context *c = talloc_get_type(ctx->async.private_data,
928 : struct composite_context);
929 0 : struct pipe_connect_state *s = talloc_get_type(c->private_data,
930 : struct pipe_connect_state);
931 :
932 0 : c->status = dcerpc_pipe_connect_ncacn_unix_stream_recv(ctx);
933 0 : if (!composite_is_ok(c)) return;
934 :
935 0 : continue_pipe_connect(c, s);
936 : }
937 :
938 :
939 : /*
940 : Stage 3 of pipe_connect_b: Receive result of pipe connect request on local rpc
941 : */
942 1280 : static void continue_pipe_connect_ncalrpc(struct composite_context *ctx)
943 : {
944 1280 : struct composite_context *c = talloc_get_type(ctx->async.private_data,
945 : struct composite_context);
946 1280 : struct pipe_connect_state *s = talloc_get_type(c->private_data,
947 : struct pipe_connect_state);
948 :
949 1280 : c->status = dcerpc_pipe_connect_ncalrpc_recv(ctx);
950 1280 : if (!composite_is_ok(c)) return;
951 :
952 1280 : continue_pipe_connect(c, s);
953 : }
954 :
955 :
956 : /*
957 : Stage 4 of pipe_connect_b: Start an authentication on connected dcerpc pipe
958 : depending on credentials and binding flags passed.
959 : */
960 13792 : static void continue_pipe_connect(struct composite_context *c, struct pipe_connect_state *s)
961 : {
962 : struct composite_context *auth_bind_req;
963 :
964 13792 : s->pipe->binding = dcerpc_binding_dup(s->pipe, s->binding);
965 13792 : if (composite_nomem(s->pipe->binding, c)) {
966 0 : return;
967 : }
968 :
969 13792 : auth_bind_req = dcerpc_pipe_auth_send(s->pipe, s->binding, s->table,
970 : s->credentials, s->lp_ctx);
971 13792 : composite_continue(c, auth_bind_req, continue_pipe_auth, c);
972 : }
973 :
974 :
975 : /*
976 : Stage 5 of pipe_connect_b: Receive result of pipe authentication request
977 : and say if all went ok
978 : */
979 13792 : static void continue_pipe_auth(struct composite_context *ctx)
980 : {
981 13792 : struct composite_context *c = talloc_get_type(ctx->async.private_data,
982 : struct composite_context);
983 13792 : struct pipe_connect_state *s = talloc_get_type(c->private_data, struct pipe_connect_state);
984 :
985 13792 : c->status = dcerpc_pipe_auth_recv(ctx, s, &s->pipe);
986 13792 : if (!composite_is_ok(c)) return;
987 :
988 13767 : composite_done(c);
989 : }
990 :
991 :
992 : /*
993 : handle timeouts of a dcerpc connect
994 : */
995 0 : static void dcerpc_connect_timeout_handler(struct tevent_context *ev, struct tevent_timer *te,
996 : struct timeval t, void *private_data)
997 : {
998 0 : struct composite_context *c = talloc_get_type_abort(private_data,
999 : struct composite_context);
1000 0 : struct pipe_connect_state *s = talloc_get_type_abort(c->private_data, struct pipe_connect_state);
1001 0 : if (!s->pipe->inhibit_timeout_processing) {
1002 0 : composite_error(c, NT_STATUS_IO_TIMEOUT);
1003 : } else {
1004 0 : s->pipe->timed_out = true;
1005 : }
1006 0 : }
1007 :
1008 : /*
1009 : start a request to open a rpc connection to a rpc pipe, using
1010 : specified binding structure to determine the endpoint and options
1011 : */
1012 23581 : _PUBLIC_ struct composite_context* dcerpc_pipe_connect_b_send(TALLOC_CTX *parent_ctx,
1013 : const struct dcerpc_binding *binding,
1014 : const struct ndr_interface_table *table,
1015 : struct cli_credentials *credentials,
1016 : struct tevent_context *ev,
1017 : struct loadparm_context *lp_ctx)
1018 : {
1019 : struct composite_context *c;
1020 : struct pipe_connect_state *s;
1021 : enum dcerpc_transport_t transport;
1022 23581 : const char *endpoint = NULL;
1023 23581 : struct cli_credentials *epm_creds = NULL;
1024 :
1025 : /* composite context allocation and setup */
1026 23581 : c = composite_create(parent_ctx, ev);
1027 23581 : if (c == NULL) {
1028 0 : return NULL;
1029 : }
1030 :
1031 23581 : s = talloc_zero(c, struct pipe_connect_state);
1032 23581 : if (composite_nomem(s, c)) return c;
1033 23581 : c->private_data = s;
1034 :
1035 : /* initialise dcerpc pipe structure */
1036 23581 : s->pipe = dcerpc_pipe_init(c, ev);
1037 23581 : if (composite_nomem(s->pipe, c)) return c;
1038 :
1039 23581 : if (DEBUGLEVEL >= 10)
1040 0 : s->pipe->conn->packet_log_dir = lpcfg_lock_directory(lp_ctx);
1041 :
1042 : /* store parameters in state structure */
1043 23581 : s->binding = dcerpc_binding_dup(s, binding);
1044 23581 : if (composite_nomem(s->binding, c)) return c;
1045 23581 : s->table = table;
1046 23581 : s->credentials = credentials;
1047 23581 : s->lp_ctx = lp_ctx;
1048 :
1049 23581 : s->pipe->timed_out = false;
1050 23581 : s->pipe->inhibit_timeout_processing = false;
1051 :
1052 23581 : tevent_add_timer(c->event_ctx, c,
1053 : timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0),
1054 : dcerpc_connect_timeout_handler, c);
1055 :
1056 23581 : transport = dcerpc_binding_get_transport(s->binding);
1057 :
1058 23581 : switch (transport) {
1059 23182 : case NCACN_NP:
1060 : case NCACN_IP_TCP:
1061 : case NCALRPC:
1062 23182 : endpoint = dcerpc_binding_get_string_option(s->binding, "endpoint");
1063 :
1064 : /* anonymous credentials for rpc connection used to get endpoint mapping */
1065 23182 : epm_creds = cli_credentials_init_anon(s);
1066 23182 : if (composite_nomem(epm_creds, c)) return c;
1067 :
1068 23182 : break;
1069 0 : case NCACN_HTTP:
1070 0 : endpoint = dcerpc_binding_get_string_option(s->binding, "endpoint");
1071 0 : epm_creds = credentials;
1072 0 : break;
1073 399 : default:
1074 399 : DBG_INFO("Unknown transport; continuing with anon, no endpoint.\n");
1075 399 : epm_creds = cli_credentials_init_anon(s);
1076 399 : if (composite_nomem(epm_creds, c)){
1077 0 : return c;
1078 : }
1079 399 : break;
1080 : }
1081 :
1082 23581 : if (endpoint == NULL) {
1083 : struct composite_context *binding_req;
1084 :
1085 43230 : binding_req = dcerpc_epm_map_binding_send(c, s->binding, s->table,
1086 : epm_creds,
1087 22777 : s->pipe->conn->event_ctx,
1088 : s->lp_ctx);
1089 22777 : composite_continue(c, binding_req, continue_map_binding, c);
1090 22777 : return c;
1091 : }
1092 :
1093 804 : continue_connect(c, s);
1094 804 : return c;
1095 : }
1096 :
1097 :
1098 : /*
1099 : receive result of a request to open a rpc connection to a rpc pipe
1100 : */
1101 23578 : _PUBLIC_ NTSTATUS dcerpc_pipe_connect_b_recv(struct composite_context *c, TALLOC_CTX *mem_ctx,
1102 : struct dcerpc_pipe **p)
1103 : {
1104 : NTSTATUS status;
1105 : struct pipe_connect_state *s;
1106 :
1107 23578 : status = composite_wait(c);
1108 :
1109 23578 : if (NT_STATUS_IS_OK(status)) {
1110 13767 : s = talloc_get_type(c->private_data, struct pipe_connect_state);
1111 13767 : talloc_steal(mem_ctx, s->pipe);
1112 13767 : *p = s->pipe;
1113 : }
1114 23578 : talloc_free(c);
1115 23578 : return status;
1116 : }
1117 :
1118 :
1119 : /*
1120 : open a rpc connection to a rpc pipe, using the specified
1121 : binding structure to determine the endpoint and options - sync version
1122 : */
1123 3990 : _PUBLIC_ NTSTATUS dcerpc_pipe_connect_b(TALLOC_CTX *parent_ctx,
1124 : struct dcerpc_pipe **pp,
1125 : const struct dcerpc_binding *binding,
1126 : const struct ndr_interface_table *table,
1127 : struct cli_credentials *credentials,
1128 : struct tevent_context *ev,
1129 : struct loadparm_context *lp_ctx)
1130 : {
1131 : struct composite_context *c;
1132 :
1133 3990 : c = dcerpc_pipe_connect_b_send(parent_ctx, binding, table,
1134 : credentials, ev, lp_ctx);
1135 3990 : return dcerpc_pipe_connect_b_recv(c, parent_ctx, pp);
1136 : }
1137 :
1138 :
1139 : struct pipe_conn_state {
1140 : struct dcerpc_pipe *pipe;
1141 : };
1142 :
1143 :
1144 : static void continue_pipe_connect_b(struct composite_context *ctx);
1145 :
1146 :
1147 : /*
1148 : Initiate rpc connection to a rpc pipe, using the specified string
1149 : binding to determine the endpoint and options.
1150 : The string is to be parsed to a binding structure first.
1151 : */
1152 4284 : _PUBLIC_ struct composite_context* dcerpc_pipe_connect_send(TALLOC_CTX *parent_ctx,
1153 : const char *binding,
1154 : const struct ndr_interface_table *table,
1155 : struct cli_credentials *credentials,
1156 : struct tevent_context *ev, struct loadparm_context *lp_ctx)
1157 : {
1158 : struct composite_context *c;
1159 : struct pipe_conn_state *s;
1160 : struct dcerpc_binding *b;
1161 : struct composite_context *pipe_conn_req;
1162 :
1163 : /* composite context allocation and setup */
1164 4284 : c = composite_create(parent_ctx, ev);
1165 4284 : if (c == NULL) {
1166 0 : return NULL;
1167 : }
1168 :
1169 4284 : s = talloc_zero(c, struct pipe_conn_state);
1170 4284 : if (composite_nomem(s, c)) return c;
1171 4284 : c->private_data = s;
1172 :
1173 : /* parse binding string to the structure */
1174 4284 : c->status = dcerpc_parse_binding(c, binding, &b);
1175 4284 : if (!NT_STATUS_IS_OK(c->status)) {
1176 0 : DEBUG(0, ("Failed to parse dcerpc binding '%s'\n", binding));
1177 0 : composite_error(c, c->status);
1178 0 : return c;
1179 : }
1180 :
1181 4284 : DEBUG(3, ("Using binding %s\n", dcerpc_binding_string(c, b)));
1182 :
1183 : /*
1184 : start connecting to a rpc pipe after binding structure
1185 : is established
1186 : */
1187 4284 : pipe_conn_req = dcerpc_pipe_connect_b_send(c, b, table,
1188 : credentials, ev, lp_ctx);
1189 4284 : composite_continue(c, pipe_conn_req, continue_pipe_connect_b, c);
1190 4284 : return c;
1191 : }
1192 :
1193 :
1194 : /*
1195 : Stage 2 of pipe_connect: Receive result of actual pipe connect request
1196 : and say if we're done ok
1197 : */
1198 4283 : static void continue_pipe_connect_b(struct composite_context *ctx)
1199 : {
1200 4283 : struct composite_context *c = talloc_get_type(ctx->async.private_data,
1201 : struct composite_context);
1202 4283 : struct pipe_conn_state *s = talloc_get_type(c->private_data,
1203 : struct pipe_conn_state);
1204 :
1205 4283 : c->status = dcerpc_pipe_connect_b_recv(ctx, c, &s->pipe);
1206 4283 : talloc_steal(s, s->pipe);
1207 4283 : if (!composite_is_ok(c)) return;
1208 :
1209 4272 : composite_done(c);
1210 : }
1211 :
1212 :
1213 : /*
1214 : Receive result of pipe connect (using binding string) request
1215 : and return connected pipe structure.
1216 : */
1217 4284 : NTSTATUS dcerpc_pipe_connect_recv(struct composite_context *c,
1218 : TALLOC_CTX *mem_ctx,
1219 : struct dcerpc_pipe **pp)
1220 : {
1221 : NTSTATUS status;
1222 : struct pipe_conn_state *s;
1223 :
1224 4284 : status = composite_wait(c);
1225 4283 : if (NT_STATUS_IS_OK(status)) {
1226 4272 : s = talloc_get_type(c->private_data, struct pipe_conn_state);
1227 4272 : *pp = talloc_steal(mem_ctx, s->pipe);
1228 : }
1229 4283 : talloc_free(c);
1230 4283 : return status;
1231 : }
1232 :
1233 :
1234 : /*
1235 : Open a rpc connection to a rpc pipe, using the specified string
1236 : binding to determine the endpoint and options - sync version
1237 : */
1238 4284 : _PUBLIC_ NTSTATUS dcerpc_pipe_connect(TALLOC_CTX *parent_ctx,
1239 : struct dcerpc_pipe **pp,
1240 : const char *binding,
1241 : const struct ndr_interface_table *table,
1242 : struct cli_credentials *credentials,
1243 : struct tevent_context *ev,
1244 : struct loadparm_context *lp_ctx)
1245 : {
1246 : struct composite_context *c;
1247 4284 : c = dcerpc_pipe_connect_send(parent_ctx, binding,
1248 : table, credentials, ev, lp_ctx);
1249 4284 : return dcerpc_pipe_connect_recv(c, parent_ctx, pp);
1250 : }
1251 :
|