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