r26651: libsmb: Allow specifying signing policy from higher up.
[npower/samba.git] / source4 / librpc / rpc / dcerpc_connect.c
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 "librpc/rpc/dcerpc.h"
33 #include "auth/credentials/credentials.h"
34 #include "param/param.h"
35 #include "libcli/resolve/resolve.h"
36
37
38 struct pipe_np_smb_state {
39         struct smb_composite_connect conn;
40         struct smbcli_tree *tree;
41         struct dcerpc_pipe_connect io;
42 };
43
44
45 /*
46   Stage 3 of ncacn_np_smb: Named pipe opened (or not)
47 */
48 static void continue_pipe_open_smb(struct composite_context *ctx)
49 {
50         struct composite_context *c = talloc_get_type(ctx->async.private_data,
51                                                       struct composite_context);
52
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;
56
57         composite_done(c);
58 }
59
60
61 /*
62   Stage 2 of ncacn_np_smb: Open a named pipe after successful smb connection
63 */
64 static void continue_smb_connect(struct composite_context *ctx)
65 {
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);
71         
72         /* receive result of smb connect request */
73         c->status = smb_composite_connect_recv(ctx, c);
74         if (!composite_is_ok(c)) return;
75
76         /* prepare named pipe open parameters */
77         s->tree         = s->conn.out.tree;
78         s->io.pipe_name = s->io.binding->endpoint;
79
80         /* send named pipe open request */
81         open_ctx = dcerpc_pipe_open_smb_send(s->io.pipe, s->tree, s->io.pipe_name);
82         if (composite_nomem(open_ctx, c)) return;
83
84         composite_continue(c, open_ctx, continue_pipe_open_smb, c);
85 }
86
87
88 /*
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
91 */
92 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)
93 {
94         struct composite_context *c;
95         struct pipe_np_smb_state *s;
96         struct composite_context *conn_req;
97         struct smb_composite_connect *conn;
98
99         /* composite context allocation and setup */
100         c = composite_create(mem_ctx, io->pipe->conn->event_ctx);
101         if (c == NULL) return NULL;
102
103         s = talloc_zero(c, struct pipe_np_smb_state);
104         if (composite_nomem(s, c)) return c;
105         c->private_data = s;
106
107         s->io  = *io;
108         conn   = &s->conn;
109
110         /* prepare smb connection parameters: we're connecting to IPC$ share on
111            remote rpc server */
112         conn->in.dest_host              = s->io.binding->host;
113         conn->in.dest_ports                  = lp_smb_ports(lp_ctx);
114         if (s->io.binding->target_hostname == NULL)
115                 conn->in.called_name = "*SMBSERVER"; /* FIXME: This is invalid */
116         else
117                 conn->in.called_name            = s->io.binding->target_hostname;
118         conn->in.service                = "IPC$";
119         conn->in.service_type           = NULL;
120         conn->in.workgroup              = lp_workgroup(lp_ctx);
121
122         conn->in.max_xmit = lp_max_xmit(lp_ctx);
123         conn->in.max_mux = lp_maxmux(lp_ctx);
124         conn->in.ntstatus_support = lp_nt_status_support(lp_ctx);
125         conn->in.max_protocol = lp_cli_maxprotocol(lp_ctx);
126         conn->in.unicode = lp_unicode(lp_ctx);
127         conn->in.use_spnego = lp_use_spnego(lp_ctx) && lp_nt_status_support(lp_ctx);
128         conn->in.signing = lp_client_signing(lp_ctx);
129
130         /*
131          * provide proper credentials - user supplied, but allow a
132          * fallback to anonymous if this is an schannel connection
133          * (might be NT4 not allowing machine logins at session
134          * setup).
135          */
136         s->conn.in.credentials = s->io.creds;
137         if (s->io.binding->flags & DCERPC_SCHANNEL) {
138                 conn->in.fallback_to_anonymous  = true;
139         } else {
140                 conn->in.fallback_to_anonymous  = false;
141         }
142
143         /* send smb connect request */
144         conn_req = smb_composite_connect_send(conn, s->io.pipe->conn, 
145                                               lp_resolve_context(lp_ctx), 
146                                               s->io.pipe->conn->event_ctx);
147         if (composite_nomem(conn_req, c)) return c;
148
149         composite_continue(c, conn_req, continue_smb_connect, c);
150         return c;
151 }
152
153
154 /*
155   Receive result of a rpc connection to a rpc pipe on SMB
156 */
157 static NTSTATUS dcerpc_pipe_connect_ncacn_np_smb_recv(struct composite_context *c)
158 {
159         NTSTATUS status = composite_wait(c);
160
161         talloc_free(c);
162         return status;
163 }
164
165
166 struct pipe_np_smb2_state {
167         struct smb2_tree *tree;
168         struct dcerpc_pipe_connect io;
169 };
170
171
172 /*
173   Stage 3 of ncacn_np_smb: Named pipe opened (or not)
174 */
175 static void continue_pipe_open_smb2(struct composite_context *ctx)
176 {
177         struct composite_context *c = talloc_get_type(ctx->async.private_data,
178                                                       struct composite_context);
179
180         /* receive result of named pipe open request on smb2 */
181         c->status = dcerpc_pipe_open_smb2_recv(ctx);
182         if (!composite_is_ok(c)) return;
183
184         composite_done(c);
185 }
186
187
188 /*
189   Stage 2 of ncacn_np_smb2: Open a named pipe after successful smb2 connection
190 */
191 static void continue_smb2_connect(struct composite_context *ctx)
192 {
193         struct composite_context *open_req;
194         struct composite_context *c = talloc_get_type(ctx->async.private_data,
195                                                       struct composite_context);
196         struct pipe_np_smb2_state *s = talloc_get_type(c->private_data,
197                                                        struct pipe_np_smb2_state);
198
199         /* receive result of smb2 connect request */
200         c->status = smb2_connect_recv(ctx, c, &s->tree);
201         if (!composite_is_ok(c)) return;
202
203         /* prepare named pipe open parameters */
204         s->io.pipe_name = s->io.binding->endpoint;
205
206         /* send named pipe open request */
207         open_req = dcerpc_pipe_open_smb2_send(s->io.pipe, s->tree, s->io.pipe_name);
208         if (composite_nomem(open_req, c)) return;
209
210         composite_continue(c, open_req, continue_pipe_open_smb2, c);
211 }
212
213
214 /* 
215    Initiate async open of a rpc connection request on SMB2 using
216    the binding structure to determine the endpoint and options
217 */
218 static struct composite_context *dcerpc_pipe_connect_ncacn_np_smb2_send(
219                                         TALLOC_CTX *mem_ctx,
220                                         struct dcerpc_pipe_connect *io,
221                                         struct loadparm_context *lp_ctx)
222 {
223         struct composite_context *c;
224         struct pipe_np_smb2_state *s;
225         struct composite_context *conn_req;
226
227         /* composite context allocation and setup */
228         c = composite_create(mem_ctx, io->pipe->conn->event_ctx);
229         if (c == NULL) return NULL;
230
231         s = talloc_zero(c, struct pipe_np_smb2_state);
232         if (composite_nomem(s, c)) return c;
233         c->private_data = s;
234
235         s->io = *io;
236
237         /*
238          * provide proper credentials - user supplied or anonymous in case this is
239          * schannel connection
240          */
241         if (s->io.binding->flags & DCERPC_SCHANNEL) {
242                 s->io.creds = cli_credentials_init(mem_ctx);
243                 if (composite_nomem(s->io.creds, c)) return c;
244
245                 cli_credentials_guess(s->io.creds, lp_ctx);
246         }
247
248         /* send smb2 connect request */
249         conn_req = smb2_connect_send(mem_ctx, s->io.binding->host, "IPC$", 
250                                      s->io.resolve_ctx,
251                                      s->io.creds,
252                                      c->event_ctx);
253         composite_continue(c, conn_req, continue_smb2_connect, c);
254         return c;
255 }
256
257
258 /*
259   Receive result of a rpc connection to a rpc pipe on SMB2
260 */
261 static NTSTATUS dcerpc_pipe_connect_ncacn_np_smb2_recv(struct composite_context *c)
262 {
263         NTSTATUS status = composite_wait(c);
264         
265         talloc_free(c);
266         return status;
267 }
268
269
270 struct pipe_ip_tcp_state {
271         struct dcerpc_pipe_connect io;
272         const char *host;
273         const char *target_hostname;
274         uint32_t port;
275 };
276
277
278 /*
279   Stage 2 of ncacn_ip_tcp: rpc pipe opened (or not)
280 */
281 static void continue_pipe_open_ncacn_ip_tcp(struct composite_context *ctx)
282 {
283         struct composite_context *c = talloc_get_type(ctx->async.private_data,
284                                                       struct composite_context);
285
286         /* receive result of named pipe open request on tcp/ip */
287         c->status = dcerpc_pipe_open_tcp_recv(ctx);
288         if (!composite_is_ok(c)) return;
289
290         composite_done(c);
291 }
292
293
294 /*
295   Initiate async open of a rpc connection to a rpc pipe on TCP/IP using
296   the binding structure to determine the endpoint and options
297 */
298 static struct composite_context* dcerpc_pipe_connect_ncacn_ip_tcp_send(TALLOC_CTX *mem_ctx,
299                                                                        struct dcerpc_pipe_connect *io)
300 {
301         struct composite_context *c;
302         struct pipe_ip_tcp_state *s;
303         struct composite_context *pipe_req;
304
305         /* composite context allocation and setup */
306         c = composite_create(mem_ctx, io->pipe->conn->event_ctx);
307         if (c == NULL) return NULL;
308
309         s = talloc_zero(c, struct pipe_ip_tcp_state);
310         if (composite_nomem(s, c)) return c;
311         c->private_data = s;
312
313         /* store input parameters in state structure */
314         s->io               = *io;
315         s->host             = talloc_reference(c, io->binding->host);
316         s->target_hostname  = talloc_reference(c, io->binding->target_hostname);
317                              /* port number is a binding endpoint here */
318         s->port             = atoi(io->binding->endpoint);   
319
320         /* send pipe open request on tcp/ip */
321         pipe_req = dcerpc_pipe_open_tcp_send(s->io.pipe->conn, s->host, s->target_hostname, 
322                                              s->port, io->resolve_ctx);
323         composite_continue(c, pipe_req, continue_pipe_open_ncacn_ip_tcp, c);
324         return c;
325 }
326
327
328 /*
329   Receive result of a rpc connection to a rpc pipe on TCP/IP
330 */
331 static NTSTATUS dcerpc_pipe_connect_ncacn_ip_tcp_recv(struct composite_context *c)
332 {
333         NTSTATUS status = composite_wait(c);
334         
335         talloc_free(c);
336         return status;
337 }
338
339
340 struct pipe_unix_state {
341         struct dcerpc_pipe_connect io;
342         const char *path;
343 };
344
345
346 /*
347   Stage 2 of ncacn_unix: rpc pipe opened (or not)
348 */
349 static void continue_pipe_open_ncacn_unix_stream(struct composite_context *ctx)
350 {
351         struct composite_context *c = talloc_get_type(ctx->async.private_data,
352                                                       struct composite_context);
353
354         /* receive result of pipe open request on unix socket */
355         c->status = dcerpc_pipe_open_unix_stream_recv(ctx);
356         if (!composite_is_ok(c)) return;
357
358         composite_done(c);
359 }
360
361
362 /*
363   Initiate async open of a rpc connection to a rpc pipe on unix socket using
364   the binding structure to determine the endpoint and options
365 */
366 static struct composite_context* dcerpc_pipe_connect_ncacn_unix_stream_send(TALLOC_CTX *mem_ctx,
367                                                                             struct dcerpc_pipe_connect *io)
368 {
369         struct composite_context *c;
370         struct pipe_unix_state *s;
371         struct composite_context *pipe_req;
372
373         /* composite context allocation and setup */
374         c = composite_create(mem_ctx, io->pipe->conn->event_ctx);
375         if (c == NULL) return NULL;
376
377         s = talloc_zero(c, struct pipe_unix_state);
378         if (composite_nomem(s, c)) return c;
379         c->private_data = s;
380
381         /* prepare pipe open parameters and store them in state structure
382            also, verify whether biding endpoint is not null */
383         s->io = *io;
384         
385         if (!io->binding->endpoint) {
386                 DEBUG(0, ("Path to unix socket not specified\n"));
387                 composite_error(c, NT_STATUS_INVALID_PARAMETER);
388                 return c;
389         }
390
391         s->path  = talloc_strdup(c, io->binding->endpoint);  /* path is a binding endpoint here */
392         if (composite_nomem(s->path, c)) return c;
393
394         /* send pipe open request on unix socket */
395         pipe_req = dcerpc_pipe_open_unix_stream_send(s->io.pipe->conn, s->path);
396         composite_continue(c, pipe_req, continue_pipe_open_ncacn_unix_stream, c);
397         return c;
398 }
399
400
401 /*
402   Receive result of a rpc connection to a pipe on unix socket
403 */
404 static NTSTATUS dcerpc_pipe_connect_ncacn_unix_stream_recv(struct composite_context *c)
405 {
406         NTSTATUS status = composite_wait(c);
407
408         talloc_free(c);
409         return status;
410 }
411
412
413 struct pipe_ncalrpc_state {
414         struct dcerpc_pipe_connect io;
415 };
416
417 static NTSTATUS dcerpc_pipe_connect_ncalrpc_recv(struct composite_context *c);
418
419 /*
420   Stage 2 of ncalrpc: rpc pipe opened (or not)
421 */
422 static void continue_pipe_open_ncalrpc(struct composite_context *ctx)
423 {
424         struct composite_context *c = talloc_get_type(ctx->async.private_data,
425                                                       struct composite_context);
426
427         /* receive result of pipe open request on ncalrpc */
428         c->status = dcerpc_pipe_connect_ncalrpc_recv(ctx);
429         if (!composite_is_ok(c)) return;
430
431         composite_done(c);
432 }
433
434
435 /* 
436    Initiate async open of a rpc connection request on NCALRPC using
437    the binding structure to determine the endpoint and options
438 */
439 static struct composite_context* dcerpc_pipe_connect_ncalrpc_send(TALLOC_CTX *mem_ctx,
440                                                                   struct dcerpc_pipe_connect *io, struct loadparm_context *lp_ctx)
441 {
442         struct composite_context *c;
443         struct pipe_ncalrpc_state *s;
444         struct composite_context *pipe_req;
445
446         /* composite context allocation and setup */
447         c = composite_create(mem_ctx, io->pipe->conn->event_ctx);
448         if (c == NULL) return NULL;
449
450         s = talloc_zero(c, struct pipe_ncalrpc_state);
451         if (composite_nomem(s, c)) return c;
452         c->private_data = s;
453         
454         /* store input parameters in state structure */
455         s->io  = *io;
456
457         /* send pipe open request */
458         pipe_req = dcerpc_pipe_open_pipe_send(s->io.pipe->conn, lp_ncalrpc_dir(lp_ctx), 
459                                               s->io.binding->endpoint);
460         composite_continue(c, pipe_req, continue_pipe_open_ncalrpc, c);
461         return c;
462 }
463
464
465 /*
466   Receive result of a rpc connection to a rpc pipe on NCALRPC
467 */
468 static NTSTATUS dcerpc_pipe_connect_ncalrpc_recv(struct composite_context *c)
469 {
470         NTSTATUS status = composite_wait(c);
471         
472         talloc_free(c);
473         return status;
474 }
475
476
477 struct pipe_connect_state {
478         struct dcerpc_pipe *pipe;
479         struct dcerpc_binding *binding;
480         const struct ndr_interface_table *table;
481         struct cli_credentials *credentials;
482         struct loadparm_context *lp_ctx;
483 };
484
485
486 static void continue_map_binding(struct composite_context *ctx);
487 static void continue_connect(struct composite_context *c, struct pipe_connect_state *s);
488 static void continue_pipe_connect_ncacn_np_smb2(struct composite_context *ctx);
489 static void continue_pipe_connect_ncacn_np_smb(struct composite_context *ctx);
490 static void continue_pipe_connect_ncacn_ip_tcp(struct composite_context *ctx);
491 static void continue_pipe_connect_ncacn_unix(struct composite_context *ctx);
492 static void continue_pipe_connect_ncalrpc(struct composite_context *ctx);
493 static void continue_pipe_connect(struct composite_context *c, struct pipe_connect_state *s);
494 static void continue_pipe_auth(struct composite_context *ctx);
495
496
497 /*
498   Stage 2 of pipe_connect_b: Receive result of endpoint mapping
499 */
500 static void continue_map_binding(struct composite_context *ctx)
501 {
502         struct composite_context *c = talloc_get_type(ctx->async.private_data,
503                                                       struct composite_context);
504         struct pipe_connect_state *s = talloc_get_type(c->private_data,
505                                                        struct pipe_connect_state);
506         
507         c->status = dcerpc_epm_map_binding_recv(ctx);
508         if (!composite_is_ok(c)) return;
509
510         DEBUG(2,("Mapped to DCERPC endpoint %s\n", s->binding->endpoint));
511         
512         continue_connect(c, s);
513 }
514
515
516 /*
517   Stage 2 of pipe_connect_b: Continue connection after endpoint is known
518 */
519 static void continue_connect(struct composite_context *c, struct pipe_connect_state *s)
520 {
521         struct dcerpc_pipe_connect pc;
522
523         /* potential exits to another stage by sending an async request */
524         struct composite_context *ncacn_np_smb2_req;
525         struct composite_context *ncacn_np_smb_req;
526         struct composite_context *ncacn_ip_tcp_req;
527         struct composite_context *ncacn_unix_req;
528         struct composite_context *ncalrpc_req;
529
530         /* dcerpc pipe connect input parameters */
531         pc.pipe         = s->pipe;
532         pc.binding      = s->binding;
533         pc.interface    = s->table;
534         pc.creds        = s->credentials;
535         pc.resolve_ctx  = lp_resolve_context(s->lp_ctx);
536
537         /* connect dcerpc pipe depending on required transport */
538         switch (s->binding->transport) {
539         case NCACN_NP:
540                 if (pc.binding->flags & DCERPC_SMB2) {
541                         /* new varient of SMB a.k.a. SMB2 */
542                         ncacn_np_smb2_req = dcerpc_pipe_connect_ncacn_np_smb2_send(c, &pc, s->lp_ctx);
543                         composite_continue(c, ncacn_np_smb2_req, continue_pipe_connect_ncacn_np_smb2, c);
544                         return;
545
546                 } else {
547                         /* good old ordinary SMB */
548                         ncacn_np_smb_req = dcerpc_pipe_connect_ncacn_np_smb_send(c, &pc, s->lp_ctx);
549                         composite_continue(c, ncacn_np_smb_req, continue_pipe_connect_ncacn_np_smb, c);
550                         return;
551                 }
552                 break;
553
554         case NCACN_IP_TCP:
555                 ncacn_ip_tcp_req = dcerpc_pipe_connect_ncacn_ip_tcp_send(c, &pc);
556                 composite_continue(c, ncacn_ip_tcp_req, continue_pipe_connect_ncacn_ip_tcp, c);
557                 return;
558
559         case NCACN_UNIX_STREAM:
560                 ncacn_unix_req = dcerpc_pipe_connect_ncacn_unix_stream_send(c, &pc);
561                 composite_continue(c, ncacn_unix_req, continue_pipe_connect_ncacn_unix, c);
562                 return;
563
564         case NCALRPC:
565                 ncalrpc_req = dcerpc_pipe_connect_ncalrpc_send(c, &pc, s->lp_ctx);
566                 composite_continue(c, ncalrpc_req, continue_pipe_connect_ncalrpc, c);
567                 return;
568
569         default:
570                 /* looks like a transport we don't support now */
571                 composite_error(c, NT_STATUS_NOT_SUPPORTED);
572         }
573 }
574
575
576 /*
577   Stage 3 of pipe_connect_b: Receive result of pipe connect request on
578   named pipe on smb2
579 */
580 static void continue_pipe_connect_ncacn_np_smb2(struct composite_context *ctx)
581 {
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);
586
587         c->status = dcerpc_pipe_connect_ncacn_np_smb2_recv(ctx);
588         if (!composite_is_ok(c)) return;
589
590         continue_pipe_connect(c, s);
591 }
592
593
594 /*
595   Stage 3 of pipe_connect_b: Receive result of pipe connect request on
596   named pipe on smb
597 */
598 static void continue_pipe_connect_ncacn_np_smb(struct composite_context *ctx)
599 {
600         struct composite_context *c = talloc_get_type(ctx->async.private_data,
601                                                       struct composite_context);
602         struct pipe_connect_state *s = talloc_get_type(c->private_data,
603                                                        struct pipe_connect_state);
604
605         c->status = dcerpc_pipe_connect_ncacn_np_smb_recv(ctx);
606         if (!composite_is_ok(c)) return;
607         
608         continue_pipe_connect(c, s);
609 }
610
611
612 /*
613   Stage 3 of pipe_connect_b: Receive result of pipe connect request on tcp/ip
614 */
615 static void continue_pipe_connect_ncacn_ip_tcp(struct composite_context *ctx)
616 {
617         struct composite_context *c = talloc_get_type(ctx->async.private_data,
618                                                       struct composite_context);
619         struct pipe_connect_state *s = talloc_get_type(c->private_data,
620                                                        struct pipe_connect_state);
621
622         c->status = dcerpc_pipe_connect_ncacn_ip_tcp_recv(ctx);
623         if (!composite_is_ok(c)) return;
624
625         continue_pipe_connect(c, s);
626 }
627
628
629 /*
630   Stage 3 of pipe_connect_b: Receive result of pipe connect request on unix socket
631 */
632 static void continue_pipe_connect_ncacn_unix(struct composite_context *ctx)
633 {
634         struct composite_context *c = talloc_get_type(ctx->async.private_data,
635                                                       struct composite_context);
636         struct pipe_connect_state *s = talloc_get_type(c->private_data,
637                                                        struct pipe_connect_state);
638         
639         c->status = dcerpc_pipe_connect_ncacn_unix_stream_recv(ctx);
640         if (!composite_is_ok(c)) return;
641         
642         continue_pipe_connect(c, s);
643 }
644
645
646 /*
647   Stage 3 of pipe_connect_b: Receive result of pipe connect request on local rpc
648 */
649 static void continue_pipe_connect_ncalrpc(struct composite_context *ctx)
650 {
651         struct composite_context *c = talloc_get_type(ctx->async.private_data,
652                                                       struct composite_context);
653         struct pipe_connect_state *s = talloc_get_type(c->private_data,
654                                                        struct pipe_connect_state);
655         
656         c->status = dcerpc_pipe_connect_ncalrpc_recv(ctx);
657         if (!composite_is_ok(c)) return;
658
659         continue_pipe_connect(c, s);
660 }
661
662
663 /*
664   Stage 4 of pipe_connect_b: Start an authentication on connected dcerpc pipe
665   depending on credentials and binding flags passed.
666 */
667 static void continue_pipe_connect(struct composite_context *c, struct pipe_connect_state *s)
668 {
669         struct composite_context *auth_bind_req;
670
671         s->pipe->binding = s->binding;
672         if (!talloc_reference(s->pipe, s->binding)) {
673                 composite_error(c, NT_STATUS_NO_MEMORY);
674                 return;
675         }
676
677         auth_bind_req = dcerpc_pipe_auth_send(s->pipe, s->binding, s->table,
678                                               s->credentials, s->lp_ctx);
679         composite_continue(c, auth_bind_req, continue_pipe_auth, c);
680 }
681
682
683 /*
684   Stage 5 of pipe_connect_b: Receive result of pipe authentication request
685   and say if all went ok
686 */
687 static void continue_pipe_auth(struct composite_context *ctx)
688 {
689         struct composite_context *c = talloc_get_type(ctx->async.private_data,
690                                                       struct composite_context);
691         struct pipe_connect_state *s = talloc_get_type(c->private_data, struct pipe_connect_state);
692
693         c->status = dcerpc_pipe_auth_recv(ctx, s, &s->pipe);
694         if (!composite_is_ok(c)) return;
695
696         composite_done(c);
697 }
698
699
700 /*
701   handle timeouts of a dcerpc connect
702 */
703 static void dcerpc_connect_timeout_handler(struct event_context *ev, struct timed_event *te, 
704                                            struct timeval t, void *private)
705 {
706         struct composite_context *c = talloc_get_type(private, struct composite_context);
707         composite_error(c, NT_STATUS_IO_TIMEOUT);
708 }
709
710 /*
711   start a request to open a rpc connection to a rpc pipe, using
712   specified binding structure to determine the endpoint and options
713 */
714 struct composite_context* dcerpc_pipe_connect_b_send(TALLOC_CTX *parent_ctx,
715                                                      struct dcerpc_binding *binding,
716                                                      const struct ndr_interface_table *table,
717                                                      struct cli_credentials *credentials,
718                                                      struct event_context *ev,
719                                                      struct loadparm_context *lp_ctx)
720 {
721         struct composite_context *c;
722         struct pipe_connect_state *s;
723         struct event_context *new_ev = NULL;
724
725         if (ev == NULL) {
726                 new_ev = event_context_init(parent_ctx);
727                 if (new_ev == NULL) return NULL;
728                 ev = new_ev;
729         }
730
731         /* composite context allocation and setup */
732         c = composite_create(parent_ctx, ev);
733         if (c == NULL) {
734                 talloc_free(new_ev);
735                 return NULL;
736         }
737         talloc_steal(c, new_ev);
738
739         s = talloc_zero(c, struct pipe_connect_state);
740         if (composite_nomem(s, c)) return c;
741         c->private_data = s;
742
743         /* initialise dcerpc pipe structure */
744         s->pipe = dcerpc_pipe_init(c, ev, lp_iconv_convenience(lp_ctx));
745         if (composite_nomem(s->pipe, c)) return c;
746
747         /* store parameters in state structure */
748         s->binding      = binding;
749         s->table        = table;
750         s->credentials  = credentials;
751         s->lp_ctx       = lp_ctx;
752
753         event_add_timed(c->event_ctx, c,
754                         timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0),
755                         dcerpc_connect_timeout_handler, c);
756         
757         switch (s->binding->transport) {
758         case NCA_UNKNOWN: {
759                 struct composite_context *binding_req;
760                 binding_req = dcerpc_epm_map_binding_send(c, s->binding, s->table,
761                                                           s->pipe->conn->event_ctx,
762                                                           s->lp_ctx);
763                 composite_continue(c, binding_req, continue_map_binding, c);
764                 return c;
765                 }
766
767         case NCACN_NP:
768         case NCACN_IP_TCP:
769         case NCALRPC:
770                 if (!s->binding->endpoint) {
771                         struct composite_context *binding_req;
772                         binding_req = dcerpc_epm_map_binding_send(c, s->binding, s->table,
773                                                                   s->pipe->conn->event_ctx,
774                                                                   s->lp_ctx);
775                         composite_continue(c, binding_req, continue_map_binding, c);
776                         return c;
777                 }
778
779         default:
780                 break;
781         }
782
783         continue_connect(c, s);
784         return c;
785 }
786
787
788 /*
789   receive result of a request to open a rpc connection to a rpc pipe
790 */
791 NTSTATUS dcerpc_pipe_connect_b_recv(struct composite_context *c, TALLOC_CTX *mem_ctx,
792                                     struct dcerpc_pipe **p)
793 {
794         NTSTATUS status;
795         struct pipe_connect_state *s;
796         
797         status = composite_wait(c);
798         
799         if (NT_STATUS_IS_OK(status)) {
800                 s = talloc_get_type(c->private_data, struct pipe_connect_state);
801                 talloc_steal(mem_ctx, s->pipe);
802                 *p = s->pipe;
803         }
804         talloc_free(c);
805         return status;
806 }
807
808
809 /*
810   open a rpc connection to a rpc pipe, using the specified 
811   binding structure to determine the endpoint and options - sync version
812 */
813 NTSTATUS dcerpc_pipe_connect_b(TALLOC_CTX *parent_ctx,
814                                struct dcerpc_pipe **pp,
815                                struct dcerpc_binding *binding,
816                                const struct ndr_interface_table *table,
817                                struct cli_credentials *credentials,
818                                struct event_context *ev,
819                                struct loadparm_context *lp_ctx)
820 {
821         struct composite_context *c;
822         
823         c = dcerpc_pipe_connect_b_send(parent_ctx, binding, table,
824                                        credentials, ev, lp_ctx);
825         return dcerpc_pipe_connect_b_recv(c, parent_ctx, pp);
826 }
827
828
829 struct pipe_conn_state {
830         struct dcerpc_pipe *pipe;
831 };
832
833
834 static void continue_pipe_connect_b(struct composite_context *ctx);
835
836
837 /*
838   Initiate rpc connection to a rpc pipe, using the specified string
839   binding to determine the endpoint and options.
840   The string is to be parsed to a binding structure first.
841 */
842 struct composite_context* dcerpc_pipe_connect_send(TALLOC_CTX *parent_ctx,
843                                                    const char *binding,
844                                                    const struct ndr_interface_table *table,
845                                                    struct cli_credentials *credentials,
846                                                    struct event_context *ev, struct loadparm_context *lp_ctx)
847 {
848         struct composite_context *c;
849         struct pipe_conn_state *s;
850         struct dcerpc_binding *b;
851         struct composite_context *pipe_conn_req;
852         struct event_context *new_ev = NULL;
853
854         if (ev == NULL) {
855                 new_ev = event_context_init(parent_ctx);
856                 if (new_ev == NULL) return NULL;
857                 ev = new_ev;
858         }
859
860         /* composite context allocation and setup */
861         c = composite_create(parent_ctx, ev);
862         if (c == NULL) {
863                 talloc_free(new_ev);
864                 return NULL;
865         }
866         talloc_steal(c, new_ev);
867
868         s = talloc_zero(c, struct pipe_conn_state);
869         if (composite_nomem(s, c)) return c;
870         c->private_data = s;
871
872         /* parse binding string to the structure */
873         c->status = dcerpc_parse_binding(c, binding, &b);
874         if (!NT_STATUS_IS_OK(c->status)) {
875                 DEBUG(0, ("Failed to parse dcerpc binding '%s'\n", binding));
876                 composite_error(c, c->status);
877                 return c;
878         }
879
880         DEBUG(3, ("Using binding %s\n", dcerpc_binding_string(c, b)));
881
882         /* 
883            start connecting to a rpc pipe after binding structure
884            is established
885          */
886         pipe_conn_req = dcerpc_pipe_connect_b_send(c, b, table,
887                                                    credentials, ev, lp_ctx);
888         composite_continue(c, pipe_conn_req, continue_pipe_connect_b, c);
889         return c;
890 }
891
892
893 /*
894   Stage 2 of pipe_connect: Receive result of actual pipe connect request
895   and say if we're done ok
896 */
897 static void continue_pipe_connect_b(struct composite_context *ctx)
898 {
899         struct composite_context *c = talloc_get_type(ctx->async.private_data,
900                                                       struct composite_context);
901         struct pipe_conn_state *s = talloc_get_type(c->private_data,
902                                                     struct pipe_conn_state);
903
904         c->status = dcerpc_pipe_connect_b_recv(ctx, c, &s->pipe);
905         talloc_steal(s, s->pipe);
906         if (!composite_is_ok(c)) return;
907
908         composite_done(c);
909 }
910
911
912 /*
913   Receive result of pipe connect (using binding string) request
914   and return connected pipe structure.
915 */
916 NTSTATUS dcerpc_pipe_connect_recv(struct composite_context *c,
917                                   TALLOC_CTX *mem_ctx,
918                                   struct dcerpc_pipe **pp)
919 {
920         NTSTATUS status;
921         struct pipe_conn_state *s;
922
923         status = composite_wait(c);
924         if (NT_STATUS_IS_OK(status)) {
925                 s = talloc_get_type(c->private_data, struct pipe_conn_state);
926                 *pp = talloc_steal(mem_ctx, s->pipe);
927         }
928         talloc_free(c);
929         return status;
930 }
931
932
933 /*
934   Open a rpc connection to a rpc pipe, using the specified string
935   binding to determine the endpoint and options - sync version
936 */
937 NTSTATUS dcerpc_pipe_connect(TALLOC_CTX *parent_ctx, 
938                              struct dcerpc_pipe **pp, 
939                              const char *binding,
940                              const struct ndr_interface_table *table,
941                              struct cli_credentials *credentials,
942                              struct event_context *ev,
943                              struct loadparm_context *lp_ctx)
944 {
945         struct composite_context *c;
946         c = dcerpc_pipe_connect_send(parent_ctx, binding, 
947                                      table, credentials, ev, lp_ctx);
948         return dcerpc_pipe_connect_recv(c, parent_ctx, pp);
949 }
950