~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source4/librpc/rpc/dcerpc_connect.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

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