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