root/source4/librpc/rpc/dcerpc_connect.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. continue_pipe_open_smb
  2. continue_smb_connect
  3. dcerpc_pipe_connect_ncacn_np_smb_send
  4. dcerpc_pipe_connect_ncacn_np_smb_recv
  5. continue_pipe_open_smb2
  6. continue_smb2_connect
  7. dcerpc_pipe_connect_ncacn_np_smb2_send
  8. dcerpc_pipe_connect_ncacn_np_smb2_recv
  9. continue_pipe_open_ncacn_ip_tcp
  10. dcerpc_pipe_connect_ncacn_ip_tcp_send
  11. dcerpc_pipe_connect_ncacn_ip_tcp_recv
  12. continue_pipe_open_ncacn_unix_stream
  13. dcerpc_pipe_connect_ncacn_unix_stream_send
  14. dcerpc_pipe_connect_ncacn_unix_stream_recv
  15. continue_pipe_open_ncalrpc
  16. dcerpc_pipe_connect_ncalrpc_send
  17. dcerpc_pipe_connect_ncalrpc_recv
  18. continue_map_binding
  19. continue_connect
  20. continue_pipe_connect_ncacn_np_smb2
  21. continue_pipe_connect_ncacn_np_smb
  22. continue_pipe_connect_ncacn_ip_tcp
  23. continue_pipe_connect_ncacn_unix
  24. continue_pipe_connect_ncalrpc
  25. continue_pipe_connect
  26. continue_pipe_auth
  27. dcerpc_connect_timeout_handler
  28. dcerpc_pipe_connect_b_send
  29. dcerpc_pipe_connect_b_recv
  30. dcerpc_pipe_connect_b
  31. dcerpc_pipe_connect_send
  32. continue_pipe_connect_b
  33. dcerpc_pipe_connect_recv
  34. dcerpc_pipe_connect

   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)
     /* [<][>][^][v][top][bottom][index][help] */
  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)
     /* [<][>][^][v][top][bottom][index][help] */
  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)
     /* [<][>][^][v][top][bottom][index][help] */
  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)
     /* [<][>][^][v][top][bottom][index][help] */
 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)
     /* [<][>][^][v][top][bottom][index][help] */
 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)
     /* [<][>][^][v][top][bottom][index][help] */
 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(
     /* [<][>][^][v][top][bottom][index][help] */
 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)
     /* [<][>][^][v][top][bottom][index][help] */
 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)
     /* [<][>][^][v][top][bottom][index][help] */
 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,
     /* [<][>][^][v][top][bottom][index][help] */
 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)
     /* [<][>][^][v][top][bottom][index][help] */
 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)
     /* [<][>][^][v][top][bottom][index][help] */
 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,
     /* [<][>][^][v][top][bottom][index][help] */
 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)
     /* [<][>][^][v][top][bottom][index][help] */
 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)
     /* [<][>][^][v][top][bottom][index][help] */
 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,
     /* [<][>][^][v][top][bottom][index][help] */
 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)
     /* [<][>][^][v][top][bottom][index][help] */
 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)
     /* [<][>][^][v][top][bottom][index][help] */
 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)
     /* [<][>][^][v][top][bottom][index][help] */
 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)
     /* [<][>][^][v][top][bottom][index][help] */
 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)
     /* [<][>][^][v][top][bottom][index][help] */
 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)
     /* [<][>][^][v][top][bottom][index][help] */
 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)
     /* [<][>][^][v][top][bottom][index][help] */
 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)
     /* [<][>][^][v][top][bottom][index][help] */
 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)
     /* [<][>][^][v][top][bottom][index][help] */
 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)
     /* [<][>][^][v][top][bottom][index][help] */
 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, 
     /* [<][>][^][v][top][bottom][index][help] */
 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,
     /* [<][>][^][v][top][bottom][index][help] */
 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,
     /* [<][>][^][v][top][bottom][index][help] */
 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,
     /* [<][>][^][v][top][bottom][index][help] */
 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,
     /* [<][>][^][v][top][bottom][index][help] */
 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)
     /* [<][>][^][v][top][bottom][index][help] */
 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,
     /* [<][>][^][v][top][bottom][index][help] */
 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, 
     /* [<][>][^][v][top][bottom][index][help] */
 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 

/* [<][>][^][v][top][bottom][index][help] */