r15500: Add support for interactive prompting on bad passwords to the RPC libraries.
[bbaumbach/samba-autobuild/.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
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 2 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, write to the Free Software
23    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
25
26
27 #include "includes.h"
28 #include "smb.h"
29 #include "libcli/composite/composite.h"
30 #include "libcli/smb_composite/smb_composite.h"
31 #include "lib/events/events.h"
32 #include "libcli/smb2/smb2.h"
33 #include "libcli/smb2/smb2_calls.h"
34 #include "librpc/rpc/dcerpc.h"
35 #include "auth/credentials/credentials.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->conn, 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 struct composite_context *dcerpc_pipe_connect_ncacn_np_smb_send(TALLOC_CTX *mem_ctx, 
93                                                                 struct dcerpc_pipe_connect *io)
94 {
95         struct composite_context *c;
96         struct pipe_np_smb_state *s;
97         struct composite_context *conn_req;
98         struct smb_composite_connect *conn;
99
100         /* composite context allocation and setup */
101         c = talloc_zero(mem_ctx, struct composite_context);
102         if (c == NULL) return NULL;
103
104         s = talloc_zero(c, struct pipe_np_smb_state);
105         if (composite_nomem(s, c)) return c;
106
107         c->state = COMPOSITE_STATE_IN_PROGRESS;
108         c->private_data = s;
109         c->event_ctx = io->pipe->conn->event_ctx;
110
111         s->io  = *io;
112         conn   = &s->conn;
113
114         /* prepare smb connection parameters: we're connecting to IPC$ share on
115            remote rpc server */
116         conn->in.dest_host              = s->io.binding->host;
117         conn->in.port                   = 0;
118         conn->in.called_name            = strupper_talloc(mem_ctx, s->io.binding->host);
119         conn->in.service                = "IPC$";
120         conn->in.service_type           = NULL;
121         conn->in.workgroup              = lp_workgroup();
122
123         /* verify if called_name has been allocated when uppercasing */
124         if (composite_nomem(conn->in.called_name, c)) return c;
125
126         /*
127          * provide proper credentials - user supplied, but allow a
128          * fallback to anonymous if this is an schannel connection
129          * (might be NT4 not allowing machine logins at session
130          * setup).
131          */
132         s->conn.in.credentials = s->io.creds;
133         if (s->io.binding->flags & DCERPC_SCHANNEL) {
134                 conn->in.fallback_to_anonymous  = True;
135         } else {
136                 conn->in.fallback_to_anonymous  = False;
137         }
138
139         /* send smb connect request */
140         conn_req = smb_composite_connect_send(conn, s->io.pipe->conn, s->io.pipe->conn->event_ctx);
141         if (composite_nomem(conn_req, c)) return c;
142
143         composite_continue(c, conn_req, continue_smb_connect, c);
144         return c;
145 }
146
147
148 /*
149   Receive result of a rpc connection to a rpc pipe on SMB
150 */
151 NTSTATUS dcerpc_pipe_connect_ncacn_np_smb_recv(struct composite_context *c)
152 {
153         NTSTATUS status = composite_wait(c);
154
155         talloc_free(c);
156         return status;
157 }
158
159
160 /*
161   Sync version of a rpc connection to a rpc pipe on SMB
162 */
163 NTSTATUS dcerpc_pipe_connect_ncacn_np_smb(TALLOC_CTX *mem_ctx,
164                                           struct dcerpc_pipe_connect *io)
165 {
166         struct composite_context *c;
167         c = dcerpc_pipe_connect_ncacn_np_smb_send(mem_ctx, io);
168         return dcerpc_pipe_connect_ncacn_np_smb_recv(c);
169 }
170
171
172 struct pipe_np_smb2_state {
173         struct smb2_tree *tree;
174         struct dcerpc_pipe_connect io;
175 };
176
177
178 /*
179   Stage 3 of ncacn_np_smb: Named pipe opened (or not)
180 */
181 static void continue_pipe_open_smb2(struct composite_context *ctx)
182 {
183         struct composite_context *c = talloc_get_type(ctx->async.private_data,
184                                                       struct composite_context);
185
186         /* receive result of named pipe open request on smb2 */
187         c->status = dcerpc_pipe_open_smb2_recv(ctx);
188         if (!composite_is_ok(c)) return;
189
190         composite_done(c);
191 }
192
193
194 /*
195   Stage 2 of ncacn_np_smb2: Open a named pipe after successful smb2 connection
196 */
197 static void continue_smb2_connect(struct composite_context *ctx)
198 {
199         struct composite_context *open_req;
200         struct composite_context *c = talloc_get_type(ctx->async.private_data,
201                                                       struct composite_context);
202         struct pipe_np_smb2_state *s = talloc_get_type(c->private_data,
203                                                        struct pipe_np_smb2_state);
204
205         /* receive result of smb2 connect request */
206         c->status = smb2_connect_recv(ctx, c, &s->tree);
207         if (!composite_is_ok(c)) return;
208
209         /* prepare named pipe open parameters */
210         s->io.pipe_name = s->io.binding->endpoint;
211
212         /* send named pipe open request */
213         open_req = dcerpc_pipe_open_smb2_send(s->io.pipe->conn, s->tree, s->io.pipe_name);
214         if (composite_nomem(open_req, c)) return;
215
216         composite_continue(c, open_req, continue_pipe_open_smb2, c);
217 }
218
219
220 /* 
221    Initiate async open of a rpc connection request on SMB2 using
222    the binding structure to determine the endpoint and options
223 */
224 struct composite_context *dcerpc_pipe_connect_ncacn_np_smb2_send(TALLOC_CTX *mem_ctx,
225                                                                  struct dcerpc_pipe_connect *io)
226 {
227         struct composite_context *c;
228         struct pipe_np_smb2_state *s;
229         struct composite_context *conn_req;
230
231         /* composite context allocation and setup */
232         c = talloc_zero(mem_ctx, struct composite_context);
233         if (c == NULL) return NULL;
234
235         s = talloc_zero(c, struct pipe_np_smb2_state);
236         if (composite_nomem(s, c)) return c;
237         
238         c->state = COMPOSITE_STATE_IN_PROGRESS;
239         c->private_data = s;
240         c->event_ctx = io->pipe->conn->event_ctx;
241
242         s->io = *io;
243
244         /*
245          * provide proper credentials - user supplied or anonymous in case this is
246          * schannel connection
247          */
248         if (s->io.binding->flags & DCERPC_SCHANNEL) {
249                 s->io.creds = cli_credentials_init(mem_ctx);
250                 if (composite_nomem(s->io.creds, c)) return c;
251
252                 cli_credentials_set_anonymous(s->io.creds);
253                 cli_credentials_guess(s->io.creds);
254         }
255
256         /* send smb2 connect request */
257         conn_req = smb2_connect_send(mem_ctx, s->io.binding->host, "IPC$", s->io.creds,
258                                      c->event_ctx);
259         if (composite_nomem(conn_req, c)) return c;
260
261         composite_continue(c, conn_req, continue_smb2_connect, c);
262
263         return c;
264 }
265
266
267 /*
268   Receive result of a rpc connection to a rpc pipe on SMB2
269 */
270 NTSTATUS dcerpc_pipe_connect_ncacn_np_smb2_recv(struct composite_context *c)
271 {
272         NTSTATUS status = composite_wait(c);
273         
274         talloc_free(c);
275         return status;
276 }
277
278
279 /*
280   Sync version of a rpc connection to a rpc pipe on SMB2
281 */
282 NTSTATUS dcerpc_pipe_connect_ncacn_np_smb2(TALLOC_CTX *mem_ctx,
283                                            struct dcerpc_pipe_connect *io)
284 {
285         struct composite_context *c;
286         c = dcerpc_pipe_connect_ncacn_np_smb2_send(mem_ctx, io);
287         return dcerpc_pipe_connect_ncacn_np_smb2_recv(c);
288 }
289
290
291 struct pipe_ip_tcp_state {
292         struct dcerpc_pipe_connect io;
293         const char *host;
294         uint32_t port;
295 };
296
297
298 /*
299   Stage 2 of ncacn_ip_tcp: rpc pipe opened (or not)
300 */
301 static void continue_pipe_open_ncacn_ip_tcp(struct composite_context *ctx)
302 {
303         struct composite_context *c = talloc_get_type(ctx->async.private_data,
304                                                       struct composite_context);
305
306         /* receive result of named pipe open request on tcp/ip */
307         c->status = dcerpc_pipe_open_tcp_recv(ctx);
308         if (!composite_is_ok(c)) return;
309
310         composite_done(c);
311 }
312
313
314 /*
315   Initiate async open of a rpc connection to a rpc pipe on TCP/IP using
316   the binding structure to determine the endpoint and options
317 */
318 struct composite_context* dcerpc_pipe_connect_ncacn_ip_tcp_send(TALLOC_CTX *mem_ctx,
319                                                                 struct dcerpc_pipe_connect *io)
320 {
321         struct composite_context *c;
322         struct pipe_ip_tcp_state *s;
323         struct composite_context *pipe_req;
324
325         /* composite context allocation and setup */
326         c = talloc_zero(mem_ctx, struct composite_context);
327         if (c == NULL) return NULL;
328
329         s = talloc_zero(c, struct pipe_ip_tcp_state);
330         if (composite_nomem(s, c)) return c;
331         
332         c->state = COMPOSITE_STATE_IN_PROGRESS;
333         c->private_data = s;
334         c->event_ctx = io->pipe->conn->event_ctx;
335
336         /* store input parameters in state structure */
337         s->io    = *io;
338         s->host  = talloc_strdup(c, io->binding->host);
339         s->port  = atoi(io->binding->endpoint);   /* port number is a binding endpoint here */
340
341         /* send pipe open request on tcp/ip */
342         pipe_req = dcerpc_pipe_open_tcp_send(s->io.pipe->conn, s->host, s->port);
343         if (composite_nomem(pipe_req, c)) return c;
344
345         composite_continue(c, pipe_req, continue_pipe_open_ncacn_ip_tcp, c);
346         return c;
347 }
348
349
350 /*
351   Receive result of a rpc connection to a rpc pipe on TCP/IP
352 */
353 NTSTATUS dcerpc_pipe_connect_ncacn_ip_tcp_recv(struct composite_context *c)
354 {
355         NTSTATUS status = composite_wait(c);
356         
357         talloc_free(c);
358         return status;
359 }
360
361
362 /*
363   Sync version of rpc connection to a rpc pipe on TCP/IP
364 */
365 NTSTATUS dcerpc_pipe_connect_ncacn_ip_tcp(TALLOC_CTX *mem_ctx,
366                                           struct dcerpc_pipe_connect *io)
367 {
368         struct composite_context *c;
369         c = dcerpc_pipe_connect_ncacn_ip_tcp_send(mem_ctx, io);
370         return dcerpc_pipe_connect_ncacn_ip_tcp_recv(c);
371 }
372
373
374 struct pipe_unix_state {
375         struct dcerpc_pipe_connect io;
376         const char *path;
377 };
378
379
380 /*
381   Stage 2 of ncacn_unix: rpc pipe opened (or not)
382 */
383 static void continue_pipe_open_ncacn_unix_stream(struct composite_context *ctx)
384 {
385         struct composite_context *c = talloc_get_type(ctx->async.private_data,
386                                                       struct composite_context);
387
388         /* receive result of pipe open request on unix socket */
389         c->status = dcerpc_pipe_open_unix_stream_recv(ctx);
390         if (!composite_is_ok(c)) return;
391
392         composite_done(c);
393 }
394
395
396 /*
397   Initiate async open of a rpc connection to a rpc pipe on unix socket using
398   the binding structure to determine the endpoint and options
399 */
400 struct composite_context* dcerpc_pipe_connect_ncacn_unix_stream_send(TALLOC_CTX *mem_ctx,
401                                                                      struct dcerpc_pipe_connect *io)
402 {
403         struct composite_context *c;
404         struct pipe_unix_state *s;
405         struct composite_context *pipe_req;
406
407         /* composite context allocation and setup */
408         c = talloc_zero(mem_ctx, struct composite_context);
409         if (c == NULL) return NULL;
410
411         s = talloc_zero(c, struct pipe_unix_state);
412         if (composite_nomem(s, c)) return c;
413         
414         c->state = COMPOSITE_STATE_IN_PROGRESS;
415         c->private_data = s;
416         c->event_ctx = io->pipe->conn->event_ctx;
417
418         /* prepare pipe open parameters and store them in state structure
419            also, verify whether biding endpoint is not null */
420         s->io = *io;
421         
422         if (!io->binding->endpoint) {
423                 DEBUG(0, ("Path to unix socket not specified\n"));
424                 composite_error(c, NT_STATUS_INVALID_PARAMETER);
425                 return c;
426         }
427
428         s->path  = talloc_strdup(c, io->binding->endpoint);  /* path is a binding endpoint here */
429
430         /* send pipe open request on unix socket */
431         pipe_req = dcerpc_pipe_open_unix_stream_send(s->io.pipe->conn, s->path);
432         if (composite_nomem(pipe_req, c)) return c;
433
434         composite_continue(c, pipe_req, continue_pipe_open_ncacn_unix_stream, c);
435         return c;
436 }
437
438
439 /*
440   Receive result of a rpc connection to a pipe on unix socket
441 */
442 NTSTATUS dcerpc_pipe_connect_ncacn_unix_stream_recv(struct composite_context *c)
443 {
444         NTSTATUS status = composite_wait(c);
445
446         talloc_free(c);
447         return status;
448 }
449
450
451 /*
452   Sync version of a rpc connection to a rpc pipe on unix socket
453 */
454 NTSTATUS dcerpc_pipe_connect_ncacn_unix_stream(TALLOC_CTX *mem_ctx,
455                                                struct dcerpc_pipe_connect *io)
456 {
457         struct composite_context *c;
458         c = dcerpc_pipe_connect_ncacn_unix_stream_send(mem_ctx, io);
459         return dcerpc_pipe_connect_ncacn_unix_stream_recv(c);   
460 }
461
462
463 struct pipe_ncalrpc_state {
464         struct dcerpc_pipe_connect io;
465 };
466
467
468 /*
469   Stage 2 of ncalrpc: rpc pipe opened (or not)
470 */
471 static void continue_pipe_open_ncalrpc(struct composite_context *ctx)
472 {
473         struct composite_context *c = talloc_get_type(ctx->async.private_data,
474                                                       struct composite_context);
475
476         /* receive result of pipe open request on ncalrpc */
477         c->status = dcerpc_pipe_connect_ncalrpc_recv(ctx);
478         if (!composite_is_ok(c)) return;
479
480         composite_done(c);
481 }
482
483
484 /* 
485    Initiate async open of a rpc connection request on NCALRPC using
486    the binding structure to determine the endpoint and options
487 */
488 struct composite_context* dcerpc_pipe_connect_ncalrpc_send(TALLOC_CTX *mem_ctx,
489                                                            struct dcerpc_pipe_connect *io)
490 {
491         struct composite_context *c;
492         struct pipe_ncalrpc_state *s;
493         struct composite_context *pipe_req;
494
495         /* composite context allocation and setup */
496         c = talloc_zero(mem_ctx, struct composite_context);
497         if (c == NULL) return NULL;
498
499         s = talloc_zero(c, struct pipe_ncalrpc_state);
500         if (composite_nomem(s, c)) return c;
501         
502         c->state = COMPOSITE_STATE_IN_PROGRESS;
503         c->private_data = s;
504         c->event_ctx = io->pipe->conn->event_ctx;
505         
506         /* store input parameters in state structure */
507         s->io  = *io;
508
509         /* send pipe open request */
510         pipe_req = dcerpc_pipe_open_pipe_send(s->io.pipe->conn, s->io.binding->endpoint);
511         if (composite_nomem(pipe_req, c)) return c;
512         
513         composite_continue(c, pipe_req, continue_pipe_open_ncalrpc, c);
514         return c;
515 }
516
517
518 /*
519   Receive result of a rpc connection to a rpc pipe on NCALRPC
520 */
521 NTSTATUS dcerpc_pipe_connect_ncalrpc_recv(struct composite_context *c)
522 {
523         NTSTATUS status = composite_wait(c);
524         
525         talloc_free(c);
526         return status;
527 }
528
529
530 /*
531   Sync version of a rpc connection to a rpc pipe on NCALRPC
532 */
533 NTSTATUS dcerpc_pipe_connect_ncalrpc(TALLOC_CTX *mem_ctx,
534                                      struct dcerpc_pipe_connect *io)
535 {
536         struct composite_context *c = dcerpc_pipe_connect_ncalrpc_send(mem_ctx, io);
537         return dcerpc_pipe_connect_ncalrpc_recv(c);
538 }
539
540
541 struct pipe_connect_state {
542         struct dcerpc_pipe *pipe;
543         struct dcerpc_binding *binding;
544         const struct dcerpc_interface_table *table;
545         struct cli_credentials *credentials;
546 };
547
548
549 static void continue_map_binding(struct composite_context *ctx);
550 static void continue_connect(struct composite_context *c, struct pipe_connect_state *s);
551 static void continue_pipe_connect_ncacn_np_smb2(struct composite_context *ctx);
552 static void continue_pipe_connect_ncacn_np_smb(struct composite_context *ctx);
553 static void continue_pipe_connect_ncacn_ip_tcp(struct composite_context *ctx);
554 static void continue_pipe_connect_ncacn_unix(struct composite_context *ctx);
555 static void continue_pipe_connect_ncalrpc(struct composite_context *ctx);
556 static void continue_pipe_connect(struct composite_context *c, struct pipe_connect_state *s);
557 static void continue_pipe_auth(struct composite_context *ctx);
558
559
560 /*
561   Stage 2 of pipe_connect_b: Receive result of endpoint mapping
562 */
563 static void continue_map_binding(struct composite_context *ctx)
564 {
565         struct composite_context *c = talloc_get_type(ctx->async.private_data,
566                                                       struct composite_context);
567         struct pipe_connect_state *s = talloc_get_type(c->private_data,
568                                                        struct pipe_connect_state);
569         
570         c->status = dcerpc_epm_map_binding_recv(ctx);
571         if (!composite_is_ok(c)) return;
572
573         DEBUG(2,("Mapped to DCERPC endpoint %s\n", s->binding->endpoint));
574         
575         continue_connect(c, s);
576 }
577
578
579 /*
580   Stage 2 of pipe_connect_b: Continue connection after endpoint is known
581 */
582 static void continue_connect(struct composite_context *c, struct pipe_connect_state *s)
583 {
584         struct dcerpc_pipe_connect pc;
585
586         /* potential exits to another stage by sending an async request */
587         struct composite_context *ncacn_np_smb2_req;
588         struct composite_context *ncacn_np_smb_req;
589         struct composite_context *ncacn_ip_tcp_req;
590         struct composite_context *ncacn_unix_req;
591         struct composite_context *ncalrpc_req;
592
593         /* dcerpc pipe connect input parameters */
594         pc.pipe         = s->pipe;
595         pc.binding      = s->binding;
596         pc.interface    = s->table;
597         pc.creds        = s->credentials;
598         
599         /* connect dcerpc pipe depending on required transport */
600         switch (s->binding->transport) {
601         case NCACN_NP:
602                 if (pc.binding->flags & DCERPC_SMB2) {
603                         /* new varient of SMB a.k.a. SMB2 */
604                         ncacn_np_smb2_req = dcerpc_pipe_connect_ncacn_np_smb2_send(c, &pc);
605                         if (composite_nomem(ncacn_np_smb2_req, c)) return;
606
607                         composite_continue(c, ncacn_np_smb2_req, continue_pipe_connect_ncacn_np_smb2, c);
608                         return;
609
610                 } else {
611                         /* good old ordinary SMB */
612                         ncacn_np_smb_req = dcerpc_pipe_connect_ncacn_np_smb_send(c, &pc);
613                         if (composite_nomem(ncacn_np_smb_req, c)) return;
614                         
615                         composite_continue(c, ncacn_np_smb_req, continue_pipe_connect_ncacn_np_smb, c);
616                         return;
617                 }
618                 break;
619
620         case NCACN_IP_TCP:
621                 ncacn_ip_tcp_req = dcerpc_pipe_connect_ncacn_ip_tcp_send(c, &pc);
622                 if (composite_nomem(ncacn_ip_tcp_req, c)) return;
623                 
624                 composite_continue(c, ncacn_ip_tcp_req, continue_pipe_connect_ncacn_ip_tcp, c);
625                 return;
626
627         case NCACN_UNIX_STREAM:
628                 ncacn_unix_req = dcerpc_pipe_connect_ncacn_unix_stream_send(c, &pc);
629                 if (composite_nomem(ncacn_unix_req, c)) return;
630                 
631                 composite_continue(c, ncacn_unix_req, continue_pipe_connect_ncacn_unix, c);
632                 return;
633
634         case NCALRPC:
635                 ncalrpc_req = dcerpc_pipe_connect_ncalrpc_send(c, &pc);
636                 if (composite_nomem(ncalrpc_req, c)) return;
637                 
638                 composite_continue(c, ncalrpc_req, continue_pipe_connect_ncalrpc, c);
639                 return;
640
641         default:
642                 /* looks like a transport we don't support now */
643                 composite_error(c, NT_STATUS_NOT_SUPPORTED);
644         }
645 }
646
647
648 /*
649   Stage 3 of pipe_connect_b: Receive result of pipe connect request on
650   named pipe on smb2
651 */
652 static void continue_pipe_connect_ncacn_np_smb2(struct composite_context *ctx)
653 {
654         struct composite_context *c = talloc_get_type(ctx->async.private_data,
655                                                       struct composite_context);
656         struct pipe_connect_state *s = talloc_get_type(c->private_data,
657                                                        struct pipe_connect_state);
658
659         c->status = dcerpc_pipe_connect_ncacn_np_smb2_recv(ctx);
660         if (!composite_is_ok(c)) return;
661
662         continue_pipe_connect(c, s);
663 }
664
665
666 /*
667   Stage 3 of pipe_connect_b: Receive result of pipe connect request on
668   named pipe on smb
669 */
670 static void continue_pipe_connect_ncacn_np_smb(struct composite_context *ctx)
671 {
672         struct composite_context *c = talloc_get_type(ctx->async.private_data,
673                                                       struct composite_context);
674         struct pipe_connect_state *s = talloc_get_type(c->private_data,
675                                                        struct pipe_connect_state);
676
677         c->status = dcerpc_pipe_connect_ncacn_np_smb_recv(ctx);
678         if (!composite_is_ok(c)) return;
679         
680         continue_pipe_connect(c, s);
681 }
682
683
684 /*
685   Stage 3 of pipe_connect_b: Receive result of pipe connect request on tcp/ip
686 */
687 static void continue_pipe_connect_ncacn_ip_tcp(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,
692                                                        struct pipe_connect_state);
693
694         c->status = dcerpc_pipe_connect_ncacn_ip_tcp_recv(ctx);
695         if (!composite_is_ok(c)) return;
696
697         continue_pipe_connect(c, s);
698 }
699
700
701 /*
702   Stage 3 of pipe_connect_b: Receive result of pipe connect request on unix socket
703 */
704 static void continue_pipe_connect_ncacn_unix(struct composite_context *ctx)
705 {
706         struct composite_context *c = talloc_get_type(ctx->async.private_data,
707                                                       struct composite_context);
708         struct pipe_connect_state *s = talloc_get_type(c->private_data,
709                                                        struct pipe_connect_state);
710         
711         c->status = dcerpc_pipe_connect_ncacn_unix_stream_recv(ctx);
712         if (!composite_is_ok(c)) return;
713         
714         continue_pipe_connect(c, s);
715 }
716
717
718 /*
719   Stage 3 of pipe_connect_b: Receive result of pipe connect request on local rpc
720 */
721 static void continue_pipe_connect_ncalrpc(struct composite_context *ctx)
722 {
723         struct composite_context *c = talloc_get_type(ctx->async.private_data,
724                                                       struct composite_context);
725         struct pipe_connect_state *s = talloc_get_type(c->private_data,
726                                                        struct pipe_connect_state);
727         
728         c->status = dcerpc_pipe_connect_ncalrpc_recv(ctx);
729         if (!composite_is_ok(c)) return;
730
731         continue_pipe_connect(c, s);
732 }
733
734
735 /*
736   Stage 4 of pipe_connect_b: Start an authentication on connected dcerpc pipe
737   depending on credentials and binding flags passed.
738 */
739 static void continue_pipe_connect(struct composite_context *c, struct pipe_connect_state *s)
740 {
741         struct composite_context *auth_bind_req;
742
743         s->pipe->binding = s->binding;
744         if (!talloc_reference(s->pipe, s->binding)) {
745                 composite_error(c, NT_STATUS_NO_MEMORY);
746                 return;
747         }
748
749         auth_bind_req = dcerpc_pipe_auth_send(s->pipe, s->binding, s->table,
750                                               s->credentials);
751         if (composite_nomem(auth_bind_req, c)) return;
752         
753         composite_continue(c, auth_bind_req, continue_pipe_auth, c);
754 }
755
756
757 /*
758   Stage 5 of pipe_connect_b: Receive result of pipe authentication request
759   and say if all went ok
760 */
761 static void continue_pipe_auth(struct composite_context *ctx)
762 {
763         struct composite_context *c = talloc_get_type(ctx->async.private_data,
764                                                       struct composite_context);
765         struct pipe_connect_state *s = talloc_get_type(c->private_data, struct pipe_connect_state);
766
767         c->status = dcerpc_pipe_auth_recv(s, &s->pipe);
768         if (!composite_is_ok(c)) return;
769
770         composite_done(c);
771 }
772
773
774 /*
775   start a request to open a rpc connection to a rpc pipe, using
776   specified binding structure to determine the endpoint and options
777 */
778 struct composite_context* dcerpc_pipe_connect_b_send(TALLOC_CTX *parent_ctx,
779                                                      struct dcerpc_binding *binding,
780                                                      const struct dcerpc_interface_table *table,
781                                                      struct cli_credentials *credentials,
782                                                      struct event_context *ev)
783 {
784         struct composite_context *c;
785         struct pipe_connect_state *s;
786
787         struct composite_context *binding_req;
788
789         /* composite context allocation and setup */
790         c = talloc_zero(parent_ctx, struct composite_context);
791         if (c == NULL) return NULL;
792
793         s = talloc_zero(c, struct pipe_connect_state);
794         if (composite_nomem(s, c)) return c;
795
796         c->state = COMPOSITE_STATE_IN_PROGRESS;
797         c->private_data = s;
798
799         if (ev == NULL) {
800                 ev = event_context_init(c);
801                 if (ev == NULL) {
802                         talloc_free(c);
803                         return NULL;
804                 }
805         }
806         c->event_ctx = ev;
807
808         /* initialise dcerpc pipe structure */
809         s->pipe = dcerpc_pipe_init(c, ev);
810         if (composite_nomem(s->pipe, c)) return c;
811
812         /* store parameters in state structure */
813         s->binding      = binding;
814         s->table        = table;
815         s->credentials  = credentials;
816         
817         switch (s->binding->transport) {
818         case NCACN_NP:
819         case NCACN_IP_TCP:
820         case NCALRPC:
821                 if (!s->binding->endpoint) {
822                         binding_req = dcerpc_epm_map_binding_send(c, s->binding, s->table,
823                                                                   s->pipe->conn->event_ctx);
824                         composite_continue(c, binding_req, continue_map_binding, c);
825                         return c;
826                 }
827
828         default:
829                 break;
830         }
831
832         continue_connect(c, s);
833         return c;
834 }
835
836
837 /*
838   receive result of a request to open a rpc connection to a rpc pipe
839 */
840 NTSTATUS dcerpc_pipe_connect_b_recv(struct composite_context *c, TALLOC_CTX *mem_ctx,
841                                     struct dcerpc_pipe **p)
842 {
843         NTSTATUS status;
844         struct pipe_connect_state *s;
845         
846         status = composite_wait(c);
847         
848         s = talloc_get_type(c->private_data, struct pipe_connect_state);
849         talloc_steal(mem_ctx, s->pipe);
850         *p = s->pipe;
851
852         talloc_free(c);
853         return status;
854 }
855
856
857 /*
858   open a rpc connection to a rpc pipe, using the specified 
859   binding structure to determine the endpoint and options - sync version
860 */
861 NTSTATUS dcerpc_pipe_connect_b(TALLOC_CTX *parent_ctx,
862                                struct dcerpc_pipe **pp,
863                                struct dcerpc_binding *binding,
864                                const struct dcerpc_interface_table *table,
865                                struct cli_credentials *credentials,
866                                struct event_context *ev)
867 {
868         struct composite_context *c;
869         
870         c = dcerpc_pipe_connect_b_send(parent_ctx, binding, table,
871                                        credentials, ev);
872         return dcerpc_pipe_connect_b_recv(c, parent_ctx, pp);
873 }
874
875
876 struct pipe_conn_state {
877         struct dcerpc_pipe *pipe;
878 };
879
880
881 static void continue_pipe_connect_b(struct composite_context *ctx);
882
883
884 /*
885   Initiate rpc connection to a rpc pipe, using the specified string
886   binding to determine the endpoint and options.
887   The string is to be parsed to a binding structure first.
888 */
889 struct composite_context* dcerpc_pipe_connect_send(TALLOC_CTX *parent_ctx,
890                                                    struct dcerpc_pipe **pp,
891                                                    const char *binding,
892                                                    const struct dcerpc_interface_table *table,
893                                                    struct cli_credentials *credentials,
894                                                    struct event_context *ev)
895 {
896         NTSTATUS status;
897         struct composite_context *c;
898         struct pipe_conn_state *s;
899         struct dcerpc_binding *b;
900         struct composite_context *pipe_conn_req;
901
902         /* composite context allocation and setup */
903         c = talloc_zero(parent_ctx, struct composite_context);
904         if (c == NULL) return NULL;
905
906         s = talloc_zero(c, struct pipe_conn_state);
907         if (composite_nomem(s, c)) return c;
908
909         c->state = COMPOSITE_STATE_IN_PROGRESS;
910         c->private_data = s;
911
912         if (ev == NULL) {
913                 ev = event_context_init(c);
914                 if (ev == NULL) {
915                         talloc_free(c);
916                         return NULL;
917                 }
918         }
919         c->event_ctx = ev;
920
921         /* parse binding string to the structure */
922         status = dcerpc_parse_binding(c, binding, &b);
923         if (!NT_STATUS_IS_OK(status)) {
924                 DEBUG(0, ("Failed to parse dcerpc binding '%s'\n", binding));
925                 composite_error(c, status);
926                 return c;
927         }
928
929         DEBUG(3, ("Using binding %s\n", dcerpc_binding_string(c, b)));
930
931         /* 
932            start connecting to a rpc pipe after binding structure
933            is established
934          */
935         pipe_conn_req = dcerpc_pipe_connect_b_send(c, b, table,
936                                                    credentials, ev);
937
938         if (composite_nomem(pipe_conn_req, c)) return c;
939
940         composite_continue(c, pipe_conn_req, continue_pipe_connect_b, c);
941         return c;
942 }
943
944
945 /*
946   Stage 2 of pipe_connect: Receive result of actual pipe connect request
947   and say if we're done ok
948 */
949 static void continue_pipe_connect_b(struct composite_context *ctx)
950 {
951         struct composite_context *c = talloc_get_type(ctx->async.private_data,
952                                                       struct composite_context);
953         struct pipe_conn_state *s = talloc_get_type(c->private_data,
954                                                     struct pipe_conn_state);
955
956         c->status = dcerpc_pipe_connect_b_recv(ctx, c, &s->pipe);
957         talloc_steal(s, s->pipe);
958         if (!composite_is_ok(c)) return;
959
960         composite_done(c);
961 }
962
963
964 /*
965   Receive result of pipe connect (using binding string) request
966   and return connected pipe structure.
967 */
968 NTSTATUS dcerpc_pipe_connect_recv(struct composite_context *c,
969                                   TALLOC_CTX *mem_ctx,
970                                   struct dcerpc_pipe **pp)
971 {
972         NTSTATUS status;
973         struct pipe_conn_state *s;
974
975         status = composite_wait(c);
976         s = talloc_get_type(c->private_data, struct pipe_conn_state);
977         *pp = talloc_steal(mem_ctx, s->pipe);
978
979         talloc_free(c);
980         return status;
981 }
982
983
984 /*
985   Open a rpc connection to a rpc pipe, using the specified string
986   binding to determine the endpoint and options - sync version
987 */
988 NTSTATUS dcerpc_pipe_connect(TALLOC_CTX *parent_ctx, 
989                              struct dcerpc_pipe **pp, 
990                              const char *binding,
991                              const struct dcerpc_interface_table *table,
992                              struct cli_credentials *credentials,
993                              struct event_context *ev)
994 {
995         struct composite_context *c;
996         c = dcerpc_pipe_connect_send(parent_ctx, pp, binding, table,
997                                      credentials, ev);
998         return dcerpc_pipe_connect_recv(c, parent_ctx, pp);
999 }
1000
1001
1002 struct sec_conn_state {
1003         struct dcerpc_pipe *pipe;
1004         struct dcerpc_pipe *pipe2;
1005         struct dcerpc_binding *binding;
1006         struct smbcli_tree *tree;
1007 };
1008
1009
1010 static void continue_open_smb(struct composite_context *ctx);
1011 static void continue_open_tcp(struct composite_context *ctx);
1012 static void continue_open_pipe(struct composite_context *ctx);
1013 static void continue_pipe_open(struct composite_context *c);
1014
1015
1016 /*
1017   Send request to create a secondary dcerpc connection from a primary
1018   connection
1019 */
1020 struct composite_context* dcerpc_secondary_connection_send(struct dcerpc_pipe *p,
1021                                                            struct dcerpc_binding *b)
1022 {
1023         struct composite_context *c;
1024         struct sec_conn_state *s;
1025         struct composite_context *pipe_smb_req;
1026         struct composite_context *pipe_tcp_req;
1027         struct composite_context *pipe_ncalrpc_req;
1028         
1029         /* composite context allocation and setup */
1030         c = talloc_zero(p, struct composite_context);
1031         if (c == NULL) return NULL;
1032
1033         c->event_ctx = p->conn->event_ctx;
1034
1035         s = talloc_zero(c, struct sec_conn_state);
1036         if (s == NULL) {
1037                 composite_error(c, NT_STATUS_NO_MEMORY);
1038                 return c;
1039         }
1040
1041         c->state = COMPOSITE_STATE_IN_PROGRESS;
1042         c->private_data = s;
1043
1044         s->pipe     = p;
1045         s->binding  = b;
1046
1047         /* initialise second dcerpc pipe based on primary pipe's event context */
1048         s->pipe2 = dcerpc_pipe_init(c, s->pipe->conn->event_ctx);
1049         if (composite_nomem(s->pipe2, c)) return c;
1050
1051         /* open second dcerpc pipe using the same transport as for primary pipe */
1052         switch (s->pipe->conn->transport.transport) {
1053         case NCACN_NP:
1054                 /* get smb tree of primary dcerpc pipe opened on smb */
1055                 s->tree = dcerpc_smb_tree(s->pipe->conn);
1056                 if (!s->tree) {
1057                         composite_error(c, NT_STATUS_INVALID_PARAMETER);
1058                         return c;
1059                 }
1060
1061                 pipe_smb_req = dcerpc_pipe_open_smb_send(s->pipe2->conn, s->tree,
1062                                                          s->binding->endpoint);
1063                 if (composite_nomem(pipe_smb_req, c)) return c;
1064
1065                 composite_continue(c, pipe_smb_req, continue_open_smb, c);
1066                 return c;
1067
1068         case NCACN_IP_TCP:
1069                 pipe_tcp_req = dcerpc_pipe_open_tcp_send(s->pipe2->conn,
1070                                                          s->binding->host,
1071                                                          atoi(s->binding->endpoint));
1072                 if (composite_nomem(pipe_tcp_req, c)) return c;
1073
1074                 composite_continue(c, pipe_tcp_req, continue_open_tcp, c);
1075                 return c;
1076
1077         case NCALRPC:
1078                 pipe_ncalrpc_req = dcerpc_pipe_open_pipe_send(s->pipe2->conn,
1079                                                               s->binding->endpoint);
1080                 if (composite_nomem(pipe_ncalrpc_req, c)) return c;
1081
1082                 composite_continue(c, pipe_ncalrpc_req, continue_open_pipe, c);
1083                 return c;
1084
1085         default:
1086                 /* looks like a transport we don't support */
1087                 composite_error(c, NT_STATUS_NOT_SUPPORTED);
1088         }
1089
1090         return c;
1091 }
1092
1093
1094 /*
1095   Stage 2 of secondary_connection: Receive result of pipe open request on smb
1096 */
1097 static void continue_open_smb(struct composite_context *ctx)
1098 {
1099         struct composite_context *c = talloc_get_type(ctx->async.private_data,
1100                                                       struct composite_context);
1101         
1102         c->status = dcerpc_pipe_open_smb_recv(ctx);
1103         if (!composite_is_ok(c)) return;
1104
1105         continue_pipe_open(c);
1106 }
1107
1108
1109 /*
1110   Stage 2 of secondary_connection: Receive result of pipe open request on tcp/ip
1111 */
1112 static void continue_open_tcp(struct composite_context *ctx)
1113 {
1114         struct composite_context *c = talloc_get_type(ctx->async.private_data,
1115                                                       struct composite_context);
1116         
1117         c->status = dcerpc_pipe_open_tcp_recv(ctx);
1118         if (!composite_is_ok(c)) return;
1119
1120         continue_pipe_open(c);
1121 }
1122
1123
1124 /*
1125   Stage 2 of secondary_connection: Receive result of pipe open request on ncalrpc
1126 */
1127 static void continue_open_pipe(struct composite_context *ctx)
1128 {
1129         struct composite_context *c = talloc_get_type(ctx->async.private_data,
1130                                                       struct composite_context);
1131
1132         c->status = dcerpc_pipe_open_pipe_recv(ctx);
1133         if (!composite_is_ok(c)) return;
1134
1135         continue_pipe_open(c);
1136 }
1137
1138
1139 /*
1140   Stage 3 of secondary_connection: Get binding data and flags from primary pipe
1141   and say if we're done ok.
1142 */
1143 static void continue_pipe_open(struct composite_context *c)
1144 {
1145         struct sec_conn_state *s;
1146
1147         s = talloc_get_type(c->private_data, struct sec_conn_state);
1148
1149         s->pipe2->conn->flags = s->pipe->conn->flags;
1150         s->pipe2->binding     = s->binding;
1151         if (!talloc_reference(s->pipe2, s->binding)) {
1152                 composite_error(c, NT_STATUS_NO_MEMORY);
1153                 return;
1154         }
1155
1156         composite_done(c);
1157 }
1158
1159
1160 /*
1161   Receive result of secondary rpc connection request and return
1162   second dcerpc pipe.
1163 */
1164 NTSTATUS dcerpc_secondary_connection_recv(struct composite_context *c,
1165                                           struct dcerpc_pipe **p2)
1166 {
1167         NTSTATUS status = composite_wait(c);
1168         struct sec_conn_state *s;
1169
1170         s = talloc_get_type(c->private_data, struct sec_conn_state);
1171
1172         if (NT_STATUS_IS_OK(status)) {
1173                 talloc_steal(s->pipe, s->pipe2);
1174                 *p2 = s->pipe2;
1175         }
1176
1177         talloc_free(c);
1178         return status;
1179 }
1180
1181 /*
1182   Create a secondary dcerpc connection from a primary connection
1183   - sync version
1184
1185   If the primary is a SMB connection then the secondary connection
1186   will be on the same SMB connection, but using a new fnum
1187 */
1188 NTSTATUS dcerpc_secondary_connection(struct dcerpc_pipe *p,
1189                                      struct dcerpc_pipe **p2,
1190                                      struct dcerpc_binding *b)
1191 {
1192         struct composite_context *c;
1193         
1194         c = dcerpc_secondary_connection_send(p, b);
1195         return dcerpc_secondary_connection_recv(c, p2);
1196 }