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 6642 : static void continue_pipe_open_smb(struct composite_context *ctx)
70 : {
71 6642 : 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 6642 : c->status = dcerpc_pipe_open_smb_recv(ctx);
76 6642 : if (!composite_is_ok(c)) return;
77 :
78 6459 : 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 26 : static void continue_smb_connect(struct composite_context *ctx)
89 : {
90 26 : struct composite_context *c = talloc_get_type(ctx->async.private_data,
91 : struct composite_context);
92 26 : struct pipe_np_smb_state *s = talloc_get_type(c->private_data,
93 : struct pipe_np_smb_state);
94 0 : struct smbcli_tree *t;
95 :
96 : /* receive result of smb connect request */
97 26 : c->status = smb_composite_connect_recv(ctx, s->io.conn);
98 26 : if (!composite_is_ok(c)) return;
99 :
100 22 : t = s->conn.out.tree;
101 :
102 : /* prepare named pipe open parameters */
103 22 : s->io.smb.conn = t->session->transport->conn;
104 22 : s->io.smb.session = t->session->smbXcli;
105 22 : s->io.smb.tcon = t->smbXcli;
106 22 : smb1cli_tcon_set_id(s->io.smb.tcon, t->tid);
107 22 : s->io.smb.pipe_name = dcerpc_binding_get_string_option(s->io.binding,
108 : "endpoint");
109 :
110 22 : continue_smb_open(c);
111 : }
112 :
113 6642 : static void continue_smb_open(struct composite_context *c)
114 : {
115 6642 : struct pipe_np_smb_state *s = talloc_get_type(c->private_data,
116 : struct pipe_np_smb_state);
117 390 : struct composite_context *open_ctx;
118 :
119 : /* send named pipe open request */
120 6642 : 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 6642 : if (composite_nomem(open_ctx, c)) return;
127 :
128 6642 : 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 6677 : 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 390 : struct composite_context *c;
139 390 : struct pipe_np_smb_state *s;
140 6677 : struct tevent_req *subreq = NULL;
141 390 : struct smb_composite_connect *conn;
142 390 : uint32_t flags;
143 6677 : const char *target_hostname = NULL;
144 6677 : const char *dest_address = NULL;
145 6677 : const char *calling_name = NULL;
146 :
147 : /* composite context allocation and setup */
148 6677 : c = composite_create(mem_ctx, io->conn->event_ctx);
149 6677 : if (c == NULL) return NULL;
150 :
151 6677 : s = talloc_zero(c, struct pipe_np_smb_state);
152 6677 : if (composite_nomem(s, c)) return c;
153 6677 : c->private_data = s;
154 :
155 6677 : s->io = *io;
156 6677 : conn = &s->conn;
157 :
158 6677 : if (smbXcli_conn_is_connected(s->io.smb.conn)) {
159 0 : continue_smb_open(c);
160 0 : return c;
161 : }
162 :
163 6677 : 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 6677 : target_hostname = dcerpc_binding_get_string_option(s->io.binding, "target_hostname");
171 6677 : conn->in.dest_host = dcerpc_binding_get_string_option(s->io.binding, "host");
172 6677 : conn->in.dest_ports = lpcfg_smb_ports(lp_ctx);
173 6677 : conn->in.called_name = target_hostname;
174 6677 : if (conn->in.called_name == NULL) {
175 0 : conn->in.called_name = "*SMBSERVER";
176 : }
177 6677 : conn->in.socket_options = lpcfg_socket_options(lp_ctx);
178 6677 : conn->in.service = "IPC$";
179 6677 : conn->in.service_type = NULL;
180 6677 : conn->in.workgroup = lpcfg_workgroup(lp_ctx);
181 6677 : conn->in.gensec_settings = lpcfg_gensec_settings(conn, lp_ctx);
182 :
183 6677 : lpcfg_smbcli_options(lp_ctx, &conn->in.options);
184 6677 : 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 6677 : s->conn.in.credentials = s->io.creds;
193 6677 : flags = dcerpc_binding_get_flags(s->io.binding);
194 6677 : if (flags & (DCERPC_SCHANNEL|DCERPC_ANON_FALLBACK)) {
195 1100 : conn->in.fallback_to_anonymous = true;
196 : } else {
197 5577 : conn->in.fallback_to_anonymous = false;
198 : }
199 :
200 6677 : conn->in.options.min_protocol = lpcfg_client_ipc_min_protocol(lp_ctx);
201 6677 : conn->in.options.max_protocol = lpcfg_client_ipc_max_protocol(lp_ctx);
202 6677 : if ((flags & DCERPC_SMB1) && (flags & DCERPC_SMB2)) {
203 : /* auto */
204 6677 : } else if (flags & DCERPC_SMB2) {
205 88 : if (conn->in.options.min_protocol < PROTOCOL_SMB2_02) {
206 84 : conn->in.options.min_protocol = PROTOCOL_SMB2_02;
207 : }
208 88 : if (conn->in.options.max_protocol < PROTOCOL_SMB2_02) {
209 0 : conn->in.options.max_protocol = PROTOCOL_LATEST;
210 : }
211 6589 : } else if (flags & DCERPC_SMB1) {
212 20 : conn->in.options.min_protocol = PROTOCOL_NT1;
213 20 : conn->in.options.max_protocol = PROTOCOL_NT1;
214 : } else {
215 : /* auto */
216 390 : }
217 :
218 6677 : conn->in.options.signing = lpcfg_client_ipc_signing(lp_ctx);
219 :
220 6677 : if (s->conn.in.credentials != NULL) {
221 6677 : calling_name = cli_credentials_get_workstation(s->conn.in.credentials);
222 : }
223 6677 : if (calling_name == NULL) {
224 9 : calling_name = "SMBCLIENT";
225 : }
226 :
227 6677 : if (target_hostname == NULL) {
228 0 : target_hostname = conn->in.dest_host;
229 : }
230 :
231 6677 : if (conn->in.dest_host != NULL && is_ipaddress(conn->in.dest_host)) {
232 787 : dest_address = conn->in.dest_host;
233 : }
234 :
235 6677 : subreq = smb_connect_nego_send(s,
236 : c->event_ctx,
237 : s->io.resolve_ctx,
238 6287 : &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 6677 : if (composite_nomem(subreq, c)) return c;
247 6677 : tevent_req_set_callback(subreq,
248 : continue_smbXcli_connect,
249 : c);
250 :
251 6677 : return c;
252 : }
253 :
254 6677 : static void continue_smbXcli_connect(struct tevent_req *subreq)
255 : {
256 390 : struct composite_context *c =
257 6677 : tevent_req_callback_data(subreq,
258 : struct composite_context);
259 390 : struct pipe_np_smb_state *s =
260 6677 : talloc_get_type_abort(c->private_data,
261 : struct pipe_np_smb_state);
262 6677 : struct smb_composite_connect *conn = &s->conn;
263 6677 : struct composite_context *creq = NULL;
264 390 : enum protocol_types protocol;
265 :
266 6677 : c->status = smb_connect_nego_recv(subreq, s,
267 : &conn->in.existing_conn);
268 6677 : TALLOC_FREE(subreq);
269 6677 : if (!composite_is_ok(c)) return;
270 :
271 6676 : protocol = smbXcli_conn_protocol(conn->in.existing_conn);
272 6676 : if (protocol >= PROTOCOL_SMB2_02) {
273 : /*
274 : * continue with smb2 session setup/tree connect
275 : * on the established connection.
276 : */
277 7040 : 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 6650 : conn->in.fallback_to_anonymous,
284 : &conn->in.existing_conn,
285 : 0, /* previous_session_id */
286 6650 : &conn->in.options,
287 : conn->in.socket_options,
288 : conn->in.gensec_settings);
289 6650 : if (composite_nomem(subreq, c)) return;
290 6650 : tevent_req_set_callback(subreq, continue_smb2_connect, c);
291 6650 : return;
292 : }
293 :
294 : /*
295 : * continue with smb1 session setup/tree connect
296 : * on the established connection.
297 : */
298 26 : creq = smb_composite_connect_send(conn, s->io.conn,
299 : s->io.resolve_ctx,
300 : c->event_ctx);
301 26 : if (composite_nomem(creq, c)) return;
302 :
303 26 : composite_continue(c, creq, continue_smb_connect, c);
304 26 : return;
305 : }
306 :
307 :
308 : /*
309 : Receive result of a rpc connection to a rpc pipe on SMB
310 : */
311 6677 : static NTSTATUS dcerpc_pipe_connect_ncacn_np_smb_recv(struct composite_context *c)
312 : {
313 6677 : NTSTATUS status = composite_wait(c);
314 :
315 6677 : talloc_free(c);
316 6677 : return status;
317 : }
318 :
319 : /*
320 : Stage 2 of ncacn_np_smb2: Open a named pipe after successful smb2 connection
321 : */
322 6650 : static void continue_smb2_connect(struct tevent_req *subreq)
323 : {
324 390 : struct composite_context *c =
325 6650 : tevent_req_callback_data(subreq,
326 : struct composite_context);
327 6650 : struct pipe_np_smb_state *s = talloc_get_type(c->private_data,
328 : struct pipe_np_smb_state);
329 390 : struct smb2_tree *t;
330 :
331 : /* receive result of smb2 connect request */
332 6650 : c->status = smb2_connect_recv(subreq, s->io.conn, &t);
333 6650 : TALLOC_FREE(subreq);
334 6650 : if (!composite_is_ok(c)) return;
335 :
336 6620 : s->io.smb.conn = t->session->transport->conn;
337 6620 : s->io.smb.session = t->session->smbXcli;
338 6620 : s->io.smb.tcon = t->smbXcli;
339 6620 : s->io.smb.pipe_name = dcerpc_binding_get_string_option(s->io.binding,
340 : "endpoint");
341 :
342 6620 : 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 15101 : static void continue_pipe_open_ncacn_ip_tcp(struct composite_context *ctx)
359 : {
360 15101 : struct composite_context *c = talloc_get_type(ctx->async.private_data,
361 : struct composite_context);
362 15101 : struct pipe_ip_tcp_state *s = talloc_get_type(c->private_data,
363 : struct pipe_ip_tcp_state);
364 15101 : char *localaddr = NULL;
365 15101 : char *remoteaddr = NULL;
366 :
367 : /* receive result of named pipe open request on tcp/ip */
368 15101 : c->status = dcerpc_pipe_open_tcp_recv(ctx, s, &localaddr, &remoteaddr);
369 15101 : if (!composite_is_ok(c)) return;
370 :
371 10607 : c->status = dcerpc_binding_set_string_option(s->io.binding,
372 : "localaddress",
373 : localaddr);
374 10607 : if (!composite_is_ok(c)) return;
375 :
376 10607 : c->status = dcerpc_binding_set_string_option(s->io.binding,
377 : "host",
378 : remoteaddr);
379 10607 : if (!composite_is_ok(c)) return;
380 :
381 10607 : 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 15102 : static struct composite_context* dcerpc_pipe_connect_ncacn_ip_tcp_send(TALLOC_CTX *mem_ctx,
390 : struct dcerpc_pipe_connect *io)
391 : {
392 242 : struct composite_context *c;
393 242 : struct pipe_ip_tcp_state *s;
394 242 : struct composite_context *pipe_req;
395 242 : const char *endpoint;
396 :
397 : /* composite context allocation and setup */
398 15102 : c = composite_create(mem_ctx, io->conn->event_ctx);
399 15102 : if (c == NULL) return NULL;
400 :
401 15102 : s = talloc_zero(c, struct pipe_ip_tcp_state);
402 15102 : if (composite_nomem(s, c)) return c;
403 15102 : c->private_data = s;
404 :
405 : /* store input parameters in state structure */
406 15102 : s->io = *io;
407 15102 : s->localaddr = dcerpc_binding_get_string_option(io->binding,
408 : "localaddress");
409 15102 : s->host = dcerpc_binding_get_string_option(io->binding, "host");
410 15102 : s->target_hostname = dcerpc_binding_get_string_option(io->binding,
411 : "target_hostname");
412 15102 : endpoint = dcerpc_binding_get_string_option(io->binding, "endpoint");
413 : /* port number is a binding endpoint here */
414 15102 : if (endpoint != NULL) {
415 15102 : s->port = atoi(endpoint);
416 : }
417 :
418 15102 : 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 15102 : pipe_req = dcerpc_pipe_open_tcp_send(s->io.conn, s->localaddr, s->host, s->target_hostname,
425 : s->port, io->resolve_ctx);
426 15102 : composite_continue(c, pipe_req, continue_pipe_open_ncacn_ip_tcp, c);
427 15102 : return c;
428 : }
429 :
430 :
431 : /*
432 : Receive result of a rpc connection to a rpc pipe on TCP/IP
433 : */
434 15101 : static NTSTATUS dcerpc_pipe_connect_ncacn_ip_tcp_recv(struct composite_context *c)
435 : {
436 15101 : NTSTATUS status = composite_wait(c);
437 :
438 15101 : talloc_free(c);
439 15101 : 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 0 : struct composite_context *c;
497 0 : struct pipe_http_state *s;
498 0 : struct tevent_req *subreq;
499 0 : const char *endpoint;
500 0 : const char *use_proxy;
501 0 : char *proxy;
502 0 : char *port;
503 0 : 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 0 : struct composite_context *c;
651 0 : struct pipe_unix_state *s;
652 0 : 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 1270 : static void continue_pipe_open_ncalrpc(struct composite_context *ctx)
701 : {
702 1270 : 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 1270 : c->status = dcerpc_pipe_connect_ncalrpc_recv(ctx);
707 1270 : if (!composite_is_ok(c)) return;
708 :
709 1270 : 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 1270 : static struct composite_context* dcerpc_pipe_connect_ncalrpc_send(TALLOC_CTX *mem_ctx,
718 : struct dcerpc_pipe_connect *io)
719 : {
720 8 : struct composite_context *c;
721 8 : struct pipe_ncalrpc_state *s;
722 8 : struct composite_context *pipe_req;
723 8 : const char *endpoint;
724 :
725 : /* composite context allocation and setup */
726 1270 : c = composite_create(mem_ctx, io->conn->event_ctx);
727 1270 : if (c == NULL) return NULL;
728 :
729 1270 : s = talloc_zero(c, struct pipe_ncalrpc_state);
730 1270 : if (composite_nomem(s, c)) return c;
731 1270 : c->private_data = s;
732 :
733 : /* store input parameters in state structure */
734 1270 : s->io = *io;
735 :
736 1270 : endpoint = dcerpc_binding_get_string_option(io->binding, "endpoint");
737 1270 : 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 1270 : pipe_req = dcerpc_pipe_open_pipe_send(s->io.conn,
744 : s->io.ncalrpc.dir,
745 : endpoint);
746 1270 : composite_continue(c, pipe_req, continue_pipe_open_ncalrpc, c);
747 1270 : return c;
748 : }
749 :
750 :
751 : /*
752 : Receive result of a rpc connection to a rpc pipe on NCALRPC
753 : */
754 2540 : static NTSTATUS dcerpc_pipe_connect_ncalrpc_recv(struct composite_context *c)
755 : {
756 2540 : NTSTATUS status = composite_wait(c);
757 :
758 2540 : talloc_free(c);
759 2540 : 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 25927 : static void continue_map_binding(struct composite_context *ctx)
787 : {
788 25927 : struct composite_context *c = talloc_get_type(ctx->async.private_data,
789 : struct composite_context);
790 25927 : struct pipe_connect_state *s = talloc_get_type(c->private_data,
791 : struct pipe_connect_state);
792 454 : const char *endpoint;
793 :
794 25927 : c->status = dcerpc_epm_map_binding_recv(ctx);
795 25927 : if (!composite_is_ok(c)) return;
796 :
797 21395 : endpoint = dcerpc_binding_get_string_option(s->binding, "endpoint");
798 21395 : DEBUG(4,("Mapped to DCERPC endpoint %s\n", endpoint));
799 :
800 21395 : continue_connect(c, s);
801 : }
802 :
803 :
804 : /*
805 : Stage 2 of pipe_connect_b: Continue connection after endpoint is known
806 : */
807 23049 : static void continue_connect(struct composite_context *c, struct pipe_connect_state *s)
808 : {
809 640 : struct dcerpc_pipe_connect pc;
810 :
811 : /* potential exits to another stage by sending an async request */
812 640 : struct composite_context *ncacn_np_smb_req;
813 640 : struct composite_context *ncacn_ip_tcp_req;
814 640 : struct composite_context *ncacn_http_req;
815 640 : struct composite_context *ncacn_unix_req;
816 640 : struct composite_context *ncalrpc_req;
817 640 : enum dcerpc_transport_t transport;
818 :
819 : /* dcerpc pipe connect input parameters */
820 23049 : ZERO_STRUCT(pc);
821 23049 : pc.conn = s->pipe->conn;
822 23049 : pc.binding = s->binding;
823 23049 : pc.interface = s->table;
824 23049 : pc.creds = s->credentials;
825 23049 : pc.resolve_ctx = lpcfg_resolve_context(s->lp_ctx);
826 :
827 23049 : transport = dcerpc_binding_get_transport(s->binding);
828 :
829 : /* connect dcerpc pipe depending on required transport */
830 23049 : switch (transport) {
831 6677 : case NCACN_NP:
832 : /*
833 : * SMB1/2/3...
834 : */
835 6677 : ncacn_np_smb_req = dcerpc_pipe_connect_ncacn_np_smb_send(c, &pc, s->lp_ctx);
836 6677 : composite_continue(c, ncacn_np_smb_req, continue_pipe_connect_ncacn_np_smb, c);
837 23439 : return;
838 :
839 15102 : case NCACN_IP_TCP:
840 15102 : ncacn_ip_tcp_req = dcerpc_pipe_connect_ncacn_ip_tcp_send(c, &pc);
841 15102 : composite_continue(c, ncacn_ip_tcp_req, continue_pipe_connect_ncacn_ip_tcp, c);
842 15102 : 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 1270 : case NCALRPC:
855 1270 : pc.ncalrpc.dir = lpcfg_ncalrpc_dir(s->lp_ctx);
856 1270 : c->status = dcerpc_binding_set_string_option(s->binding, "ncalrpc_dir",
857 : pc.ncalrpc.dir);
858 1270 : if (!composite_is_ok(c)) return;
859 1270 : ncalrpc_req = dcerpc_pipe_connect_ncalrpc_send(c, &pc);
860 1270 : composite_continue(c, ncalrpc_req, continue_pipe_connect_ncalrpc, c);
861 1270 : 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 6677 : static void continue_pipe_connect_ncacn_np_smb(struct composite_context *ctx)
875 : {
876 6677 : struct composite_context *c = talloc_get_type(ctx->async.private_data,
877 : struct composite_context);
878 6677 : struct pipe_connect_state *s = talloc_get_type(c->private_data,
879 : struct pipe_connect_state);
880 :
881 6677 : c->status = dcerpc_pipe_connect_ncacn_np_smb_recv(ctx);
882 6677 : if (!composite_is_ok(c)) return;
883 :
884 6459 : 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 15101 : static void continue_pipe_connect_ncacn_ip_tcp(struct composite_context *ctx)
892 : {
893 15101 : struct composite_context *c = talloc_get_type(ctx->async.private_data,
894 : struct composite_context);
895 15101 : struct pipe_connect_state *s = talloc_get_type(c->private_data,
896 : struct pipe_connect_state);
897 :
898 15101 : c->status = dcerpc_pipe_connect_ncacn_ip_tcp_recv(ctx);
899 15101 : if (!composite_is_ok(c)) return;
900 :
901 10607 : 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 1270 : static void continue_pipe_connect_ncalrpc(struct composite_context *ctx)
943 : {
944 1270 : struct composite_context *c = talloc_get_type(ctx->async.private_data,
945 : struct composite_context);
946 1270 : struct pipe_connect_state *s = talloc_get_type(c->private_data,
947 : struct pipe_connect_state);
948 :
949 1270 : c->status = dcerpc_pipe_connect_ncalrpc_recv(ctx);
950 1270 : if (!composite_is_ok(c)) return;
951 :
952 1270 : 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 18336 : static void continue_pipe_connect(struct composite_context *c, struct pipe_connect_state *s)
961 : {
962 640 : struct composite_context *auth_bind_req;
963 :
964 18336 : s->pipe->binding = dcerpc_binding_dup(s->pipe, s->binding);
965 18336 : if (composite_nomem(s->pipe->binding, c)) {
966 0 : return;
967 : }
968 :
969 18336 : auth_bind_req = dcerpc_pipe_auth_send(s->pipe, s->binding, s->table,
970 : s->credentials, s->lp_ctx);
971 18336 : 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 18336 : static void continue_pipe_auth(struct composite_context *ctx)
980 : {
981 18336 : struct composite_context *c = talloc_get_type(ctx->async.private_data,
982 : struct composite_context);
983 18336 : struct pipe_connect_state *s = talloc_get_type(c->private_data, struct pipe_connect_state);
984 :
985 18336 : c->status = dcerpc_pipe_auth_recv(ctx, s, &s->pipe);
986 18336 : if (!composite_is_ok(c)) return;
987 :
988 18260 : 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 27582 : _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 640 : struct composite_context *c;
1020 640 : struct pipe_connect_state *s;
1021 640 : enum dcerpc_transport_t transport;
1022 27582 : const char *endpoint = NULL;
1023 27582 : struct cli_credentials *epm_creds = NULL;
1024 :
1025 : /* composite context allocation and setup */
1026 27582 : c = composite_create(parent_ctx, ev);
1027 27582 : if (c == NULL) {
1028 0 : return NULL;
1029 : }
1030 :
1031 27582 : s = talloc_zero(c, struct pipe_connect_state);
1032 27582 : if (composite_nomem(s, c)) return c;
1033 27582 : c->private_data = s;
1034 :
1035 : /* initialise dcerpc pipe structure */
1036 27582 : s->pipe = dcerpc_pipe_init(c, ev);
1037 27582 : if (composite_nomem(s->pipe, c)) return c;
1038 :
1039 27582 : if (DEBUGLEVEL >= 10) {
1040 0 : s->pipe->conn->packet_log_dir = lpcfg_lock_directory(lp_ctx);
1041 : }
1042 :
1043 : /* store parameters in state structure */
1044 27582 : s->binding = dcerpc_binding_dup(s, binding);
1045 27582 : if (composite_nomem(s->binding, c)) return c;
1046 27582 : s->table = table;
1047 27582 : s->credentials = credentials;
1048 27582 : s->lp_ctx = lp_ctx;
1049 :
1050 27582 : s->pipe->timed_out = false;
1051 27582 : s->pipe->inhibit_timeout_processing = false;
1052 :
1053 27582 : tevent_add_timer(c->event_ctx, c,
1054 : timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0),
1055 : dcerpc_connect_timeout_handler, c);
1056 :
1057 27582 : transport = dcerpc_binding_get_transport(s->binding);
1058 :
1059 27582 : switch (transport) {
1060 26521 : case NCACN_NP:
1061 : case NCACN_IP_TCP:
1062 : case NCALRPC:
1063 26521 : endpoint = dcerpc_binding_get_string_option(s->binding, "endpoint");
1064 :
1065 : /* anonymous credentials for rpc connection used to get endpoint mapping */
1066 26521 : epm_creds = cli_credentials_init_anon(s);
1067 26521 : if (composite_nomem(epm_creds, c)) return c;
1068 :
1069 25913 : break;
1070 0 : case NCACN_HTTP:
1071 0 : endpoint = dcerpc_binding_get_string_option(s->binding, "endpoint");
1072 0 : epm_creds = credentials;
1073 0 : break;
1074 1061 : default:
1075 1061 : DBG_INFO("Unknown transport; continuing with anon, no endpoint.\n");
1076 1061 : epm_creds = cli_credentials_init_anon(s);
1077 1061 : if (composite_nomem(epm_creds, c)){
1078 0 : return c;
1079 : }
1080 1029 : break;
1081 : }
1082 :
1083 27550 : if (endpoint == NULL) {
1084 454 : struct composite_context *binding_req;
1085 :
1086 26382 : binding_req = dcerpc_epm_map_binding_send(c, s->binding, s->table,
1087 : epm_creds,
1088 25928 : s->pipe->conn->event_ctx,
1089 : s->lp_ctx);
1090 25928 : composite_continue(c, binding_req, continue_map_binding, c);
1091 25928 : return c;
1092 : }
1093 :
1094 1654 : continue_connect(c, s);
1095 1654 : return c;
1096 : }
1097 :
1098 :
1099 : /*
1100 : receive result of a request to open a rpc connection to a rpc pipe
1101 : */
1102 27580 : _PUBLIC_ NTSTATUS dcerpc_pipe_connect_b_recv(struct composite_context *c, TALLOC_CTX *mem_ctx,
1103 : struct dcerpc_pipe **p)
1104 : {
1105 640 : NTSTATUS status;
1106 640 : struct pipe_connect_state *s;
1107 :
1108 27580 : status = composite_wait(c);
1109 :
1110 27580 : if (NT_STATUS_IS_OK(status)) {
1111 18260 : s = talloc_get_type(c->private_data, struct pipe_connect_state);
1112 18260 : talloc_steal(mem_ctx, s->pipe);
1113 18260 : *p = s->pipe;
1114 : }
1115 27580 : talloc_free(c);
1116 27580 : return status;
1117 : }
1118 :
1119 :
1120 : /*
1121 : open a rpc connection to a rpc pipe, using the specified
1122 : binding structure to determine the endpoint and options - sync version
1123 : */
1124 7083 : _PUBLIC_ NTSTATUS dcerpc_pipe_connect_b(TALLOC_CTX *parent_ctx,
1125 : struct dcerpc_pipe **pp,
1126 : const struct dcerpc_binding *binding,
1127 : const struct ndr_interface_table *table,
1128 : struct cli_credentials *credentials,
1129 : struct tevent_context *ev,
1130 : struct loadparm_context *lp_ctx)
1131 : {
1132 439 : struct composite_context *c;
1133 :
1134 7083 : c = dcerpc_pipe_connect_b_send(parent_ctx, binding, table,
1135 : credentials, ev, lp_ctx);
1136 7083 : return dcerpc_pipe_connect_b_recv(c, parent_ctx, pp);
1137 : }
1138 :
1139 :
1140 : struct pipe_conn_state {
1141 : struct dcerpc_pipe *pipe;
1142 : };
1143 :
1144 :
1145 : static void continue_pipe_connect_b(struct composite_context *ctx);
1146 :
1147 :
1148 : /*
1149 : Initiate rpc connection to a rpc pipe, using the specified string
1150 : binding to determine the endpoint and options.
1151 : The string is to be parsed to a binding structure first.
1152 : */
1153 4561 : _PUBLIC_ struct composite_context* dcerpc_pipe_connect_send(TALLOC_CTX *parent_ctx,
1154 : const char *binding,
1155 : const struct ndr_interface_table *table,
1156 : struct cli_credentials *credentials,
1157 : struct tevent_context *ev, struct loadparm_context *lp_ctx)
1158 : {
1159 4 : struct composite_context *c;
1160 4 : struct pipe_conn_state *s;
1161 4 : struct dcerpc_binding *b;
1162 4 : struct composite_context *pipe_conn_req;
1163 :
1164 : /* composite context allocation and setup */
1165 4561 : c = composite_create(parent_ctx, ev);
1166 4561 : if (c == NULL) {
1167 0 : return NULL;
1168 : }
1169 :
1170 4561 : s = talloc_zero(c, struct pipe_conn_state);
1171 4561 : if (composite_nomem(s, c)) return c;
1172 4561 : c->private_data = s;
1173 :
1174 : /* parse binding string to the structure */
1175 4561 : c->status = dcerpc_parse_binding(c, binding, &b);
1176 4561 : if (!NT_STATUS_IS_OK(c->status)) {
1177 0 : DEBUG(0, ("Failed to parse dcerpc binding '%s'\n", binding));
1178 0 : composite_error(c, c->status);
1179 0 : return c;
1180 : }
1181 :
1182 4561 : DEBUG(3, ("Using binding %s\n", dcerpc_binding_string(c, b)));
1183 :
1184 : /*
1185 : start connecting to a rpc pipe after binding structure
1186 : is established
1187 : */
1188 4561 : pipe_conn_req = dcerpc_pipe_connect_b_send(c, b, table,
1189 : credentials, ev, lp_ctx);
1190 4561 : composite_continue(c, pipe_conn_req, continue_pipe_connect_b, c);
1191 4561 : return c;
1192 : }
1193 :
1194 :
1195 : /*
1196 : Stage 2 of pipe_connect: Receive result of actual pipe connect request
1197 : and say if we're done ok
1198 : */
1199 4561 : static void continue_pipe_connect_b(struct composite_context *ctx)
1200 : {
1201 4561 : struct composite_context *c = talloc_get_type(ctx->async.private_data,
1202 : struct composite_context);
1203 4561 : struct pipe_conn_state *s = talloc_get_type(c->private_data,
1204 : struct pipe_conn_state);
1205 :
1206 4561 : c->status = dcerpc_pipe_connect_b_recv(ctx, c, &s->pipe);
1207 4561 : talloc_steal(s, s->pipe);
1208 4561 : if (!composite_is_ok(c)) return;
1209 :
1210 4495 : composite_done(c);
1211 : }
1212 :
1213 :
1214 : /*
1215 : Receive result of pipe connect (using binding string) request
1216 : and return connected pipe structure.
1217 : */
1218 4561 : NTSTATUS dcerpc_pipe_connect_recv(struct composite_context *c,
1219 : TALLOC_CTX *mem_ctx,
1220 : struct dcerpc_pipe **pp)
1221 : {
1222 4 : NTSTATUS status;
1223 4 : struct pipe_conn_state *s;
1224 :
1225 4561 : status = composite_wait(c);
1226 4561 : if (NT_STATUS_IS_OK(status)) {
1227 4495 : s = talloc_get_type(c->private_data, struct pipe_conn_state);
1228 4495 : *pp = talloc_steal(mem_ctx, s->pipe);
1229 : }
1230 4561 : talloc_free(c);
1231 4561 : return status;
1232 : }
1233 :
1234 :
1235 : /*
1236 : Open a rpc connection to a rpc pipe, using the specified string
1237 : binding to determine the endpoint and options - sync version
1238 : */
1239 4561 : _PUBLIC_ NTSTATUS dcerpc_pipe_connect(TALLOC_CTX *parent_ctx,
1240 : struct dcerpc_pipe **pp,
1241 : const char *binding,
1242 : const struct ndr_interface_table *table,
1243 : struct cli_credentials *credentials,
1244 : struct tevent_context *ev,
1245 : struct loadparm_context *lp_ctx)
1246 : {
1247 4 : struct composite_context *c;
1248 4561 : c = dcerpc_pipe_connect_send(parent_ctx, binding,
1249 : table, credentials, ev, lp_ctx);
1250 4561 : return dcerpc_pipe_connect_recv(c, parent_ctx, pp);
1251 : }
1252 :
|