root/source4/libnet/libnet_rpc.c

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

DEFINITIONS

This source file includes following definitions.
  1. libnet_RpcConnectSrv_send
  2. continue_pipe_connect
  3. libnet_RpcConnectSrv_recv
  4. libnet_RpcConnectDC_send
  5. continue_lookup_dc
  6. continue_rpc_connect
  7. libnet_RpcConnectDC_recv
  8. libnet_RpcConnectDCInfo_send
  9. continue_dci_rpc_connect
  10. continue_lsa_policy
  11. continue_lsa_query_info2
  12. continue_lsa_query_info
  13. continue_epm_map_binding_send
  14. continue_epm_map_binding
  15. continue_secondary_conn
  16. libnet_RpcConnectDCInfo_recv
  17. libnet_RpcConnect_send
  18. libnet_RpcConnect_recv
  19. libnet_RpcConnect

   1 /* 
   2    Unix SMB/CIFS implementation.
   3    
   4    Copyright (C) Stefan Metzmacher  2004
   5    Copyright (C) Rafal Szczesniak   2005
   6    
   7    This program is free software; you can redistribute it and/or modify
   8    it under the terms of the GNU General Public License as published by
   9    the Free Software Foundation; either version 3 of the License, or
  10    (at your option) any later version.
  11    
  12    This program is distributed in the hope that it will be useful,
  13    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15    GNU General Public License for more details.
  16    
  17    You should have received a copy of the GNU General Public License
  18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  19 */
  20 
  21 #include "includes.h"
  22 #include "libnet/libnet.h"
  23 #include "libcli/libcli.h"
  24 #include "libcli/composite/composite.h"
  25 #include "librpc/rpc/dcerpc.h"
  26 #include "librpc/rpc/dcerpc_proto.h"
  27 #include "librpc/gen_ndr/ndr_lsa_c.h"
  28 #include "librpc/gen_ndr/ndr_samr.h"
  29 
  30 
  31 struct rpc_connect_srv_state {
  32         struct libnet_context *ctx;
  33         struct libnet_RpcConnect r;
  34         const char *binding;
  35 
  36         /* information about the progress */
  37         void (*monitor_fn)(struct monitor_msg*);
  38 };
  39 
  40 
  41 static void continue_pipe_connect(struct composite_context *ctx);
  42 
  43 
  44 /**
  45  * Initiates connection to rpc pipe on remote server
  46  * 
  47  * @param ctx initialised libnet context
  48  * @param mem_ctx memory context of this call
  49  * @param r data structure containing necessary parameters and return values
  50  * @return composite context of this call
  51  **/
  52 
  53 static struct composite_context* libnet_RpcConnectSrv_send(struct libnet_context *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
  54                                                            TALLOC_CTX *mem_ctx,
  55                                                            struct libnet_RpcConnect *r,
  56                                                            void (*monitor)(struct monitor_msg*))
  57 {
  58         struct composite_context *c;    
  59         struct rpc_connect_srv_state *s;
  60         struct dcerpc_binding *b;
  61         struct composite_context *pipe_connect_req;
  62 
  63         /* composite context allocation and setup */
  64         c = composite_create(ctx, ctx->event_ctx);
  65         if (c == NULL) return c;
  66 
  67         s = talloc_zero(c, struct rpc_connect_srv_state);
  68         if (composite_nomem(s, c)) return c;
  69 
  70         c->private_data = s;
  71         s->monitor_fn   = monitor;
  72 
  73         s->ctx = ctx;
  74         s->r = *r;
  75         ZERO_STRUCT(s->r.out);
  76 
  77         /* prepare binding string */
  78         switch (r->level) {
  79         case LIBNET_RPC_CONNECT_SERVER:
  80                 s->binding = talloc_asprintf(s, "ncacn_np:%s", r->in.name);
  81                 break;
  82         case LIBNET_RPC_CONNECT_SERVER_ADDRESS:
  83                 s->binding = talloc_asprintf(s, "ncacn_np:%s", r->in.address);
  84                 break;
  85 
  86         case LIBNET_RPC_CONNECT_BINDING:
  87                 s->binding = talloc_strdup(s, r->in.binding);
  88                 break;
  89 
  90         case LIBNET_RPC_CONNECT_DC:
  91         case LIBNET_RPC_CONNECT_PDC:
  92                 /* this should never happen - DC and PDC level has a separate
  93                    composite function */
  94         case LIBNET_RPC_CONNECT_DC_INFO:
  95                 /* this should never happen - DC_INFO level has a separate
  96                    composite function */
  97                 composite_error(c, NT_STATUS_INVALID_LEVEL);
  98                 return c;
  99         }
 100 
 101         /* parse binding string to the structure */
 102         c->status = dcerpc_parse_binding(c, s->binding, &b);
 103         if (!NT_STATUS_IS_OK(c->status)) {
 104                 DEBUG(0, ("Failed to parse dcerpc binding '%s'\n", s->binding));
 105                 composite_error(c, c->status);
 106                 return c;
 107         }
 108 
 109         if (r->level == LIBNET_RPC_CONNECT_SERVER_ADDRESS) {
 110                 b->target_hostname = talloc_reference(b, r->in.name);
 111                 if (composite_nomem(b->target_hostname, c)) {
 112                         return c;
 113                 }
 114         }
 115 
 116         /* connect to remote dcerpc pipe */
 117         pipe_connect_req = dcerpc_pipe_connect_b_send(c, b, r->in.dcerpc_iface,
 118                                                       ctx->cred, c->event_ctx,
 119                                                       ctx->lp_ctx);
 120         if (composite_nomem(pipe_connect_req, c)) return c;
 121 
 122         composite_continue(c, pipe_connect_req, continue_pipe_connect, c);
 123         return c;
 124 }
 125 
 126 
 127 /*
 128   Step 2 of RpcConnectSrv - get rpc connection
 129 */
 130 static void continue_pipe_connect(struct composite_context *ctx)
     /* [<][>][^][v][top][bottom][index][help] */
 131 {
 132         struct composite_context *c;
 133         struct rpc_connect_srv_state *s;
 134 
 135         c = talloc_get_type(ctx->async.private_data, struct composite_context);
 136         s = talloc_get_type(c->private_data, struct rpc_connect_srv_state);
 137 
 138         /* receive result of rpc pipe connection */
 139         c->status = dcerpc_pipe_connect_b_recv(ctx, c, &s->r.out.dcerpc_pipe);
 140         
 141         /* post monitor message */
 142         if (s->monitor_fn) {
 143                 struct monitor_msg msg;
 144                 struct msg_net_rpc_connect data;
 145                 struct dcerpc_binding *binding = s->r.out.dcerpc_pipe->binding;
 146                 
 147                 /* prepare monitor message and post it */
 148                 data.host        = binding->host;
 149                 data.endpoint    = binding->endpoint;
 150                 data.transport   = binding->transport;
 151                 data.domain_name = binding->target_hostname;
 152                 
 153                 msg.type      = mon_NetRpcConnect;
 154                 msg.data      = (void*)&data;
 155                 msg.data_size = sizeof(data);
 156                 s->monitor_fn(&msg);
 157         }
 158 
 159         composite_done(c);      
 160 }
 161 
 162 
 163 /**
 164  * Receives result of connection to rpc pipe on remote server
 165  *
 166  * @param c composite context
 167  * @param ctx initialised libnet context
 168  * @param mem_ctx memory context of this call
 169  * @param r data structure containing necessary parameters and return values
 170  * @return nt status of rpc connection
 171  **/
 172 
 173 static NTSTATUS libnet_RpcConnectSrv_recv(struct composite_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
 174                                           struct libnet_context *ctx,
 175                                           TALLOC_CTX *mem_ctx,
 176                                           struct libnet_RpcConnect *r)
 177 {
 178         NTSTATUS status;
 179         struct rpc_connect_srv_state *s = talloc_get_type(c->private_data,
 180                                           struct rpc_connect_srv_state);
 181 
 182         status = composite_wait(c);
 183         if (NT_STATUS_IS_OK(status)) {
 184                 /* move the returned rpc pipe between memory contexts */
 185                 s = talloc_get_type(c->private_data, struct rpc_connect_srv_state);
 186                 r->out.dcerpc_pipe = talloc_steal(mem_ctx, s->r.out.dcerpc_pipe);
 187 
 188                 /* reference created pipe structure to long-term libnet_context
 189                    so that it can be used by other api functions even after short-term
 190                    mem_ctx is freed */
 191                 if (r->in.dcerpc_iface == &ndr_table_samr) {
 192                         ctx->samr.pipe = talloc_reference(ctx, r->out.dcerpc_pipe);
 193 
 194                 } else if (r->in.dcerpc_iface == &ndr_table_lsarpc) {
 195                         ctx->lsa.pipe = talloc_reference(ctx, r->out.dcerpc_pipe);
 196                 }
 197 
 198                 r->out.error_string = talloc_strdup(mem_ctx, "Success");
 199 
 200         } else {
 201                 r->out.error_string = talloc_asprintf(mem_ctx, "Error: %s", nt_errstr(status));
 202         }
 203 
 204         talloc_free(c);
 205         return status;
 206 }
 207 
 208 
 209 struct rpc_connect_dc_state {
 210         struct libnet_context *ctx;
 211         struct libnet_RpcConnect r;
 212         struct libnet_RpcConnect r2;
 213         struct libnet_LookupDCs f;
 214         const char *connect_name;
 215 
 216         /* information about the progress */
 217         void (*monitor_fn)(struct monitor_msg *);
 218 };
 219 
 220 
 221 static void continue_lookup_dc(struct composite_context *ctx);
 222 static void continue_rpc_connect(struct composite_context *ctx);
 223 
 224 
 225 /**
 226  * Initiates connection to rpc pipe on domain pdc
 227  * 
 228  * @param ctx initialised libnet context
 229  * @param mem_ctx memory context of this call
 230  * @param r data structure containing necessary parameters and return values
 231  * @return composite context of this call
 232  **/
 233 
 234 static struct composite_context* libnet_RpcConnectDC_send(struct libnet_context *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 235                                                           TALLOC_CTX *mem_ctx,
 236                                                           struct libnet_RpcConnect *r,
 237                                                           void (*monitor)(struct monitor_msg *msg))
 238 {
 239         struct composite_context *c;
 240         struct rpc_connect_dc_state *s;
 241         struct composite_context *lookup_dc_req;
 242 
 243         /* composite context allocation and setup */
 244         c = composite_create(ctx, ctx->event_ctx);
 245         if (c == NULL) return c;
 246 
 247         s = talloc_zero(c, struct rpc_connect_dc_state);
 248         if (composite_nomem(s, c)) return c;
 249 
 250         c->private_data = s;
 251         s->monitor_fn   = monitor;
 252 
 253         s->ctx = ctx;
 254         s->r   = *r;
 255         ZERO_STRUCT(s->r.out);
 256 
 257         switch (r->level) {
 258         case LIBNET_RPC_CONNECT_PDC:
 259                 s->f.in.name_type = NBT_NAME_PDC;
 260                 break;
 261 
 262         case LIBNET_RPC_CONNECT_DC:
 263                 s->f.in.name_type = NBT_NAME_LOGON;
 264                 break;
 265 
 266         default:
 267                 break;
 268         }
 269 
 270         s->f.in.domain_name = r->in.name;
 271         s->f.out.num_dcs    = 0;
 272         s->f.out.dcs        = NULL;
 273 
 274         /* find the domain pdc first */
 275         lookup_dc_req = libnet_LookupDCs_send(ctx, c, &s->f);
 276         if (composite_nomem(lookup_dc_req, c)) return c;
 277 
 278         composite_continue(c, lookup_dc_req, continue_lookup_dc, c);
 279         return c;
 280 }
 281 
 282 
 283 /*
 284   Step 2 of RpcConnectDC: get domain controller name and
 285   initiate RpcConnect to it
 286 */
 287 static void continue_lookup_dc(struct composite_context *ctx)
     /* [<][>][^][v][top][bottom][index][help] */
 288 {
 289         struct composite_context *c;
 290         struct rpc_connect_dc_state *s;
 291         struct composite_context *rpc_connect_req;
 292         struct monitor_msg msg;
 293         struct msg_net_lookup_dc data;
 294         
 295         c = talloc_get_type(ctx->async.private_data, struct composite_context);
 296         s = talloc_get_type(c->private_data, struct rpc_connect_dc_state);
 297         
 298         /* receive result of domain controller lookup */
 299         c->status = libnet_LookupDCs_recv(ctx, c, &s->f);
 300         if (!composite_is_ok(c)) return;
 301 
 302         /* decide on preferred address type depending on DC type */
 303         s->connect_name = s->f.out.dcs[0].name;
 304 
 305         /* post monitor message */
 306         if (s->monitor_fn) {
 307                 /* prepare a monitor message and post it */
 308                 data.domain_name = s->f.in.domain_name;
 309                 data.hostname    = s->f.out.dcs[0].name;
 310                 data.address     = s->f.out.dcs[0].address;
 311                 
 312                 msg.type         = mon_NetLookupDc;
 313                 msg.data         = &data;
 314                 msg.data_size    = sizeof(data);
 315                 s->monitor_fn(&msg);
 316         }
 317 
 318         /* ok, pdc has been found so do attempt to rpc connect */
 319         s->r2.level            = LIBNET_RPC_CONNECT_SERVER_ADDRESS;
 320 
 321         /* this will cause yet another name resolution, but at least
 322          * we pass the right name down the stack now */
 323         s->r2.in.name          = talloc_strdup(s, s->connect_name);
 324         s->r2.in.address       = talloc_steal(s, s->f.out.dcs[0].address);
 325         s->r2.in.dcerpc_iface  = s->r.in.dcerpc_iface;  
 326 
 327         /* send rpc connect request to the server */
 328         rpc_connect_req = libnet_RpcConnectSrv_send(s->ctx, c, &s->r2, s->monitor_fn);
 329         if (composite_nomem(rpc_connect_req, c)) return;
 330 
 331         composite_continue(c, rpc_connect_req, continue_rpc_connect, c);
 332 }
 333 
 334 
 335 /*
 336   Step 3 of RpcConnectDC: get rpc connection to the server
 337 */
 338 static void continue_rpc_connect(struct composite_context *ctx)
     /* [<][>][^][v][top][bottom][index][help] */
 339 {
 340         struct composite_context *c;
 341         struct rpc_connect_dc_state *s;
 342 
 343         c = talloc_get_type(ctx->async.private_data, struct composite_context);
 344         s = talloc_get_type(c->private_data, struct rpc_connect_dc_state);
 345 
 346         c->status = libnet_RpcConnectSrv_recv(ctx, s->ctx, c, &s->r2);
 347 
 348         /* error string is to be passed anyway */
 349         s->r.out.error_string  = s->r2.out.error_string;
 350         if (!composite_is_ok(c)) return;
 351 
 352         s->r.out.dcerpc_pipe = s->r2.out.dcerpc_pipe;
 353         
 354         /* post monitor message */
 355         if (s->monitor_fn) {
 356                 struct monitor_msg msg;
 357                 struct msg_net_rpc_connect data;
 358                 struct dcerpc_binding *binding = s->r.out.dcerpc_pipe->binding;
 359 
 360                 data.host        = binding->host;
 361                 data.endpoint    = binding->endpoint;
 362                 data.transport   = binding->transport;
 363                 data.domain_name = binding->target_hostname;
 364                 
 365                 msg.type      = mon_NetRpcConnect;
 366                 msg.data      = (void*)&data;
 367                 msg.data_size = sizeof(data);
 368                 s->monitor_fn(&msg);
 369         }
 370 
 371         composite_done(c);
 372 }
 373 
 374 
 375 /**
 376  * Receives result of connection to rpc pipe on domain pdc
 377  *
 378  * @param c composite context
 379  * @param ctx initialised libnet context
 380  * @param mem_ctx memory context of this call
 381  * @param r data structure containing necessary parameters and return values
 382  * @return nt status of rpc connection
 383  **/
 384 
 385 static NTSTATUS libnet_RpcConnectDC_recv(struct composite_context *c,
     /* [<][>][^][v][top][bottom][index][help] */
 386                                          struct libnet_context *ctx,
 387                                          TALLOC_CTX *mem_ctx,
 388                                          struct libnet_RpcConnect *r)
 389 {
 390         NTSTATUS status;
 391         struct rpc_connect_dc_state *s = talloc_get_type(c->private_data,
 392                                          struct rpc_connect_dc_state);
 393 
 394         status = composite_wait(c);
 395         if (NT_STATUS_IS_OK(status)) {
 396                 /* move connected rpc pipe between memory contexts */
 397                 r->out.dcerpc_pipe = talloc_steal(mem_ctx, s->r.out.dcerpc_pipe);
 398 
 399                 /* reference created pipe structure to long-term libnet_context
 400                    so that it can be used by other api functions even after short-term
 401                    mem_ctx is freed */
 402                 if (r->in.dcerpc_iface == &ndr_table_samr) {
 403                         ctx->samr.pipe = talloc_reference(ctx, r->out.dcerpc_pipe);
 404 
 405                 } else if (r->in.dcerpc_iface == &ndr_table_lsarpc) {
 406                         ctx->lsa.pipe = talloc_reference(ctx, r->out.dcerpc_pipe);
 407                 }
 408 
 409         } else {
 410                 r->out.error_string = talloc_asprintf(mem_ctx,
 411                                                       "Failed to rpc connect: %s",
 412                                                       nt_errstr(status));
 413         }
 414 
 415         talloc_free(c);
 416         return status;
 417 }
 418 
 419 
 420 
 421 struct rpc_connect_dci_state {
 422         struct libnet_context *ctx;
 423         struct libnet_RpcConnect r;
 424         struct libnet_RpcConnect rpc_conn;
 425         struct policy_handle lsa_handle;
 426         struct lsa_QosInfo qos;
 427         struct lsa_ObjectAttribute attr;
 428         struct lsa_OpenPolicy2 lsa_open_policy;
 429         struct dcerpc_pipe *lsa_pipe;
 430         struct lsa_QueryInfoPolicy2 lsa_query_info2;
 431         struct lsa_QueryInfoPolicy lsa_query_info;
 432         struct dcerpc_binding *final_binding;
 433         struct dcerpc_pipe *final_pipe;
 434 
 435         /* information about the progress */
 436         void (*monitor_fn)(struct monitor_msg*);
 437 };
 438 
 439 
 440 static void continue_dci_rpc_connect(struct composite_context *ctx);
 441 static void continue_lsa_policy(struct rpc_request *req);
 442 static void continue_lsa_query_info(struct rpc_request *req);
 443 static void continue_lsa_query_info2(struct rpc_request *req);
 444 static void continue_epm_map_binding(struct composite_context *ctx);
 445 static void continue_secondary_conn(struct composite_context *ctx);
 446 static void continue_epm_map_binding_send(struct composite_context *c);
 447 
 448 
 449 /**
 450  * Initiates connection to rpc pipe on remote server or pdc. Received result
 451  * contains info on the domain name, domain sid and realm.
 452  * 
 453  * @param ctx initialised libnet context
 454  * @param mem_ctx memory context of this call
 455  * @param r data structure containing necessary parameters and return values. Must be a talloc context
 456  * @return composite context of this call
 457  **/
 458 
 459 static struct composite_context* libnet_RpcConnectDCInfo_send(struct libnet_context *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 460                                                               TALLOC_CTX *mem_ctx,
 461                                                               struct libnet_RpcConnect *r,
 462                                                               void (*monitor)(struct monitor_msg*))
 463 {
 464         struct composite_context *c, *conn_req;
 465         struct rpc_connect_dci_state *s;
 466 
 467         /* composite context allocation and setup */
 468         c = composite_create(ctx, ctx->event_ctx);
 469         if (c == NULL) return c;
 470 
 471         s = talloc_zero(c, struct rpc_connect_dci_state);
 472         if (composite_nomem(s, c)) return c;
 473 
 474         c->private_data = s;
 475         s->monitor_fn   = monitor;
 476 
 477         s->ctx = ctx;
 478         s->r   = *r;
 479         ZERO_STRUCT(s->r.out);
 480 
 481         /* proceed to pure rpc connection if the binding string is provided,
 482            otherwise try to connect domain controller */
 483         if (r->in.binding == NULL) {
 484                 s->rpc_conn.in.name    = r->in.name;
 485                 s->rpc_conn.level      = LIBNET_RPC_CONNECT_DC;
 486         } else {
 487                 s->rpc_conn.in.binding = r->in.binding;
 488                 s->rpc_conn.level      = LIBNET_RPC_CONNECT_BINDING;
 489         }
 490 
 491         /* we need to query information on lsarpc interface first */
 492         s->rpc_conn.in.dcerpc_iface    = &ndr_table_lsarpc;
 493         
 494         /* request connection to the lsa pipe on the pdc */
 495         conn_req = libnet_RpcConnect_send(ctx, c, &s->rpc_conn, s->monitor_fn);
 496         if (composite_nomem(c, conn_req)) return c;
 497 
 498         composite_continue(c, conn_req, continue_dci_rpc_connect, c);
 499         return c;
 500 }
 501 
 502 
 503 /*
 504   Step 2 of RpcConnectDCInfo: receive opened rpc pipe and open
 505   lsa policy handle
 506 */
 507 static void continue_dci_rpc_connect(struct composite_context *ctx)
     /* [<][>][^][v][top][bottom][index][help] */
 508 {
 509         struct composite_context *c;
 510         struct rpc_connect_dci_state *s;
 511         struct rpc_request *open_pol_req;
 512 
 513         c = talloc_get_type(ctx->async.private_data, struct composite_context);
 514         s = talloc_get_type(c->private_data, struct rpc_connect_dci_state);
 515 
 516         c->status = libnet_RpcConnect_recv(ctx, s->ctx, c, &s->rpc_conn);
 517         if (!NT_STATUS_IS_OK(c->status)) {
 518                 composite_error(c, c->status);
 519                 return;
 520         }
 521 
 522         /* post monitor message */
 523         if (s->monitor_fn) {
 524                 struct monitor_msg msg;
 525                 struct msg_net_rpc_connect data;
 526                 struct dcerpc_binding *binding = s->r.out.dcerpc_pipe->binding;
 527 
 528                 data.host        = binding->host;
 529                 data.endpoint    = binding->endpoint;
 530                 data.transport   = binding->transport;
 531                 data.domain_name = binding->target_hostname;
 532 
 533                 msg.type      = mon_NetRpcConnect;
 534                 msg.data      = (void*)&data;
 535                 msg.data_size = sizeof(data);
 536                 s->monitor_fn(&msg);
 537         }
 538 
 539         /* prepare to open a policy handle on lsa pipe */
 540         s->lsa_pipe = s->ctx->lsa.pipe;
 541         
 542         s->qos.len                 = 0;
 543         s->qos.impersonation_level = 2;
 544         s->qos.context_mode        = 1;
 545         s->qos.effective_only      = 0;
 546 
 547         s->attr.sec_qos = &s->qos;
 548 
 549         s->lsa_open_policy.in.attr        = &s->attr;
 550         s->lsa_open_policy.in.system_name = talloc_asprintf(c, "\\");
 551         if (composite_nomem(s->lsa_open_policy.in.system_name, c)) return;
 552 
 553         s->lsa_open_policy.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
 554         s->lsa_open_policy.out.handle     = &s->lsa_handle;
 555 
 556         open_pol_req = dcerpc_lsa_OpenPolicy2_send(s->lsa_pipe, c, &s->lsa_open_policy);
 557         if (composite_nomem(open_pol_req, c)) return;
 558 
 559         composite_continue_rpc(c, open_pol_req, continue_lsa_policy, c);
 560 }
 561 
 562 
 563 /*
 564   Step 3 of RpcConnectDCInfo: Get policy handle and query lsa info
 565   for kerberos realm (dns name) and guid. The query may fail.
 566 */
 567 static void continue_lsa_policy(struct rpc_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
 568 {
 569         struct composite_context *c;
 570         struct rpc_connect_dci_state *s;
 571         struct rpc_request *query_info_req;
 572 
 573         c = talloc_get_type(req->async.private_data, struct composite_context);
 574         s = talloc_get_type(c->private_data, struct rpc_connect_dci_state);
 575 
 576         c->status = dcerpc_ndr_request_recv(req);
 577         if (!NT_STATUS_IS_OK(c->status)) {
 578                 composite_error(c, c->status);
 579                 return;
 580         }
 581 
 582         if (NT_STATUS_EQUAL(s->lsa_open_policy.out.result, NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED)) {
 583                 s->r.out.realm = NULL;
 584                 s->r.out.guid  = NULL;
 585                 s->r.out.domain_name = NULL;
 586                 s->r.out.domain_sid  = NULL;
 587 
 588                 /* Skip to the creating the actual connection, no info available on this transport */
 589                 continue_epm_map_binding_send(c);
 590                 return;
 591 
 592         } else if (!NT_STATUS_IS_OK(s->lsa_open_policy.out.result)) {
 593                 composite_error(c, s->lsa_open_policy.out.result);
 594                 return;
 595         }
 596 
 597         /* post monitor message */
 598         if (s->monitor_fn) {
 599                 struct monitor_msg msg;
 600 
 601                 msg.type      = mon_LsaOpenPolicy;
 602                 msg.data      = NULL;
 603                 msg.data_size = 0;
 604                 s->monitor_fn(&msg);
 605         }
 606 
 607         /* query lsa info for dns domain name and guid */
 608         s->lsa_query_info2.in.handle = &s->lsa_handle;
 609         s->lsa_query_info2.in.level  = LSA_POLICY_INFO_DNS;
 610         s->lsa_query_info2.out.info  = talloc_zero(c, union lsa_PolicyInformation *);
 611         if (composite_nomem(s->lsa_query_info2.out.info, c)) return;
 612 
 613         query_info_req = dcerpc_lsa_QueryInfoPolicy2_send(s->lsa_pipe, c, &s->lsa_query_info2);
 614         if (composite_nomem(query_info_req, c)) return;
 615 
 616         composite_continue_rpc(c, query_info_req, continue_lsa_query_info2, c);
 617 }
 618 
 619 
 620 /*
 621   Step 4 of RpcConnectDCInfo: Get realm and guid if provided (rpc call
 622   may result in failure) and query lsa info for domain name and sid.
 623 */
 624 static void continue_lsa_query_info2(struct rpc_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
 625 {       
 626         struct composite_context *c;
 627         struct rpc_connect_dci_state *s;
 628         struct rpc_request *query_info_req;
 629 
 630         c = talloc_get_type(req->async.private_data, struct composite_context);
 631         s = talloc_get_type(c->private_data, struct rpc_connect_dci_state);
 632 
 633         c->status = dcerpc_ndr_request_recv(req);
 634         
 635         /* In case of error just null the realm and guid and proceed
 636            to the next step. After all, it doesn't have to be AD domain
 637            controller we talking to - NT-style PDC also counts */
 638 
 639         if (NT_STATUS_EQUAL(c->status, NT_STATUS_NET_WRITE_FAULT)) {
 640                 s->r.out.realm = NULL;
 641                 s->r.out.guid  = NULL;
 642 
 643         } else {
 644                 if (!NT_STATUS_IS_OK(c->status)) {
 645                         s->r.out.error_string = talloc_asprintf(c,
 646                                                                 "lsa_QueryInfoPolicy2 failed: %s",
 647                                                                 nt_errstr(c->status));
 648                         composite_error(c, c->status);
 649                         return;
 650                 }
 651 
 652                 if (!NT_STATUS_IS_OK(s->lsa_query_info2.out.result)) {
 653                         s->r.out.error_string = talloc_asprintf(c,
 654                                                                 "lsa_QueryInfoPolicy2 failed: %s",
 655                                                                 nt_errstr(s->lsa_query_info2.out.result));
 656                         composite_error(c, s->lsa_query_info2.out.result);
 657                         return;
 658                 }
 659 
 660                 /* Copy the dns domain name and guid from the query result */
 661 
 662                 /* this should actually be a conversion from lsa_StringLarge */
 663                 s->r.out.realm = (*s->lsa_query_info2.out.info)->dns.dns_domain.string;
 664                 s->r.out.guid  = talloc(c, struct GUID);
 665                 if (composite_nomem(s->r.out.guid, c)) {
 666                         s->r.out.error_string = NULL;
 667                         return;
 668                 }
 669                 *s->r.out.guid = (*s->lsa_query_info2.out.info)->dns.domain_guid;
 670         }
 671 
 672         /* post monitor message */
 673         if (s->monitor_fn) {
 674                 struct monitor_msg msg;
 675                 
 676                 msg.type      = mon_LsaQueryPolicy;
 677                 msg.data      = NULL;
 678                 msg.data_size = 0;
 679                 s->monitor_fn(&msg);
 680         }
 681 
 682         /* query lsa info for domain name and sid */
 683         s->lsa_query_info.in.handle = &s->lsa_handle;
 684         s->lsa_query_info.in.level  = LSA_POLICY_INFO_DOMAIN;
 685         s->lsa_query_info.out.info  = talloc_zero(c, union lsa_PolicyInformation *);
 686         if (composite_nomem(s->lsa_query_info.out.info, c)) return;
 687 
 688         query_info_req = dcerpc_lsa_QueryInfoPolicy_send(s->lsa_pipe, c, &s->lsa_query_info);
 689         if (composite_nomem(query_info_req, c)) return;
 690 
 691         composite_continue_rpc(c, query_info_req, continue_lsa_query_info, c);
 692 }
 693 
 694 
 695 /*
 696   Step 5 of RpcConnectDCInfo: Get domain name and sid
 697 */
 698 static void continue_lsa_query_info(struct rpc_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
 699 {
 700         struct composite_context *c;
 701         struct rpc_connect_dci_state *s;
 702 
 703         c = talloc_get_type(req->async.private_data, struct composite_context);
 704         s = talloc_get_type(c->private_data, struct rpc_connect_dci_state);
 705 
 706         c->status = dcerpc_ndr_request_recv(req);
 707         if (!NT_STATUS_IS_OK(c->status)) {
 708                 s->r.out.error_string = talloc_asprintf(c,
 709                                                         "lsa_QueryInfoPolicy failed: %s",
 710                                                         nt_errstr(c->status));
 711                 composite_error(c, c->status);
 712                 return;
 713         }
 714 
 715         /* post monitor message */
 716         if (s->monitor_fn) {
 717                 struct monitor_msg msg;
 718                 
 719                 msg.type      = mon_LsaQueryPolicy;
 720                 msg.data      = NULL;
 721                 msg.data_size = 0;
 722                 s->monitor_fn(&msg);
 723         }
 724 
 725         /* Copy the domain name and sid from the query result */
 726         s->r.out.domain_sid  = (*s->lsa_query_info.out.info)->domain.sid;
 727         s->r.out.domain_name = (*s->lsa_query_info.out.info)->domain.name.string;
 728 
 729         continue_epm_map_binding_send(c);
 730 }
 731 
 732 /* 
 733    Step 5 (continued) of RpcConnectDCInfo: request endpoint
 734    map binding.
 735 
 736    We may short-cut to this step if we don't support LSA OpenPolicy on this transport
 737 */
 738 static void continue_epm_map_binding_send(struct composite_context *c)
     /* [<][>][^][v][top][bottom][index][help] */
 739 {
 740         struct rpc_connect_dci_state *s;
 741         struct composite_context *epm_map_req;
 742         s = talloc_get_type(c->private_data, struct rpc_connect_dci_state);
 743 
 744         /* prepare to get endpoint mapping for the requested interface */
 745         s->final_binding = talloc(s, struct dcerpc_binding);
 746         if (composite_nomem(s->final_binding, c)) return;
 747         
 748         *s->final_binding = *s->lsa_pipe->binding;
 749         /* Ensure we keep hold of the member elements */
 750         if (composite_nomem(talloc_reference(s->final_binding, s->lsa_pipe->binding), c)) return;
 751 
 752         epm_map_req = dcerpc_epm_map_binding_send(c, s->final_binding, s->r.in.dcerpc_iface,
 753                                                   s->lsa_pipe->conn->event_ctx, s->ctx->lp_ctx);
 754         if (composite_nomem(epm_map_req, c)) return;
 755 
 756         composite_continue(c, epm_map_req, continue_epm_map_binding, c);
 757 }
 758 
 759 /*
 760   Step 6 of RpcConnectDCInfo: Receive endpoint mapping and create secondary
 761   rpc connection derived from already used pipe but connected to the requested
 762   one (as specified in libnet_RpcConnect structure)
 763 */
 764 static void continue_epm_map_binding(struct composite_context *ctx)
     /* [<][>][^][v][top][bottom][index][help] */
 765 {
 766         struct composite_context *c, *sec_conn_req;
 767         struct rpc_connect_dci_state *s;
 768 
 769         c = talloc_get_type(ctx->async.private_data, struct composite_context);
 770         s = talloc_get_type(c->private_data, struct rpc_connect_dci_state);
 771 
 772         c->status = dcerpc_epm_map_binding_recv(ctx);
 773         if (!NT_STATUS_IS_OK(c->status)) {
 774                 s->r.out.error_string = talloc_asprintf(c,
 775                                                         "failed to map pipe with endpoint mapper - %s",
 776                                                         nt_errstr(c->status));
 777                 composite_error(c, c->status);
 778                 return;
 779         }
 780 
 781         /* create secondary connection derived from lsa pipe */
 782         sec_conn_req = dcerpc_secondary_connection_send(s->lsa_pipe, s->final_binding);
 783         if (composite_nomem(sec_conn_req, c)) return;
 784 
 785         composite_continue(c, sec_conn_req, continue_secondary_conn, c);
 786 }
 787 
 788 
 789 /*
 790   Step 7 of RpcConnectDCInfo: Get actual pipe to be returned
 791   and complete this composite call
 792 */
 793 static void continue_secondary_conn(struct composite_context *ctx)
     /* [<][>][^][v][top][bottom][index][help] */
 794 {
 795         struct composite_context *c;
 796         struct rpc_connect_dci_state *s;
 797 
 798         c = talloc_get_type(ctx->async.private_data, struct composite_context);
 799         s = talloc_get_type(c->private_data, struct rpc_connect_dci_state);
 800 
 801         c->status = dcerpc_secondary_connection_recv(ctx, &s->final_pipe);
 802         if (!NT_STATUS_IS_OK(c->status)) {
 803                 s->r.out.error_string = talloc_asprintf(c,
 804                                                         "secondary connection failed: %s",
 805                                                         nt_errstr(c->status));
 806                 
 807                 composite_error(c, c->status);
 808                 return;
 809         }
 810 
 811         s->r.out.dcerpc_pipe = s->final_pipe;
 812 
 813         /* post monitor message */
 814         if (s->monitor_fn) {
 815                 struct monitor_msg msg;
 816                 struct msg_net_rpc_connect data;
 817                 struct dcerpc_binding *binding = s->r.out.dcerpc_pipe->binding;
 818                 
 819                 /* prepare monitor message and post it */
 820                 data.host        = binding->host;
 821                 data.endpoint    = binding->endpoint;
 822                 data.transport   = binding->transport;
 823                 data.domain_name = binding->target_hostname;
 824                 
 825                 msg.type      = mon_NetRpcConnect;
 826                 msg.data      = (void*)&data;
 827                 msg.data_size = sizeof(data);
 828                 s->monitor_fn(&msg);
 829         }
 830 
 831         composite_done(c);
 832 }
 833 
 834 
 835 /**
 836  * Receives result of connection to rpc pipe and gets basic
 837  * domain info (name, sid, realm, guid)
 838  *
 839  * @param c composite context
 840  * @param ctx initialised libnet context
 841  * @param mem_ctx memory context of this call
 842  * @param r data structure containing return values
 843  * @return nt status of rpc connection
 844  **/
 845 
 846 static NTSTATUS libnet_RpcConnectDCInfo_recv(struct composite_context *c, struct libnet_context *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 847                                              TALLOC_CTX *mem_ctx, struct libnet_RpcConnect *r)
 848 {
 849         NTSTATUS status;
 850         struct rpc_connect_dci_state *s = talloc_get_type(c->private_data,
 851                                           struct rpc_connect_dci_state);
 852 
 853         status = composite_wait(c);
 854         if (NT_STATUS_IS_OK(status)) {
 855                 r->out.realm        = talloc_steal(mem_ctx, s->r.out.realm);
 856                 r->out.guid         = talloc_steal(mem_ctx, s->r.out.guid);
 857                 r->out.domain_name  = talloc_steal(mem_ctx, s->r.out.domain_name);
 858                 r->out.domain_sid   = talloc_steal(mem_ctx, s->r.out.domain_sid);
 859 
 860                 r->out.dcerpc_pipe  = talloc_steal(mem_ctx, s->r.out.dcerpc_pipe);
 861 
 862                 /* reference created pipe structure to long-term libnet_context
 863                    so that it can be used by other api functions even after short-term
 864                    mem_ctx is freed */
 865                 if (r->in.dcerpc_iface == &ndr_table_samr) {
 866                         ctx->samr.pipe = talloc_reference(ctx, r->out.dcerpc_pipe);
 867 
 868                 } else if (r->in.dcerpc_iface == &ndr_table_lsarpc) {
 869                         ctx->lsa.pipe = talloc_reference(ctx, r->out.dcerpc_pipe);
 870                 }
 871 
 872         } else {
 873                 if (s->r.out.error_string) {
 874                         r->out.error_string = talloc_steal(mem_ctx, s->r.out.error_string);
 875                 } else if (r->in.binding == NULL) {
 876                         r->out.error_string = talloc_asprintf(mem_ctx, "Connection to DC failed: %s", nt_errstr(status));
 877                 } else {
 878                         r->out.error_string = talloc_asprintf(mem_ctx, "Connection to DC %s failed: %s", 
 879                                                               r->in.binding, nt_errstr(status));
 880                 }
 881         }
 882 
 883         talloc_free(c);
 884         return status;
 885 }
 886 
 887 
 888 /**
 889  * Initiates connection to rpc pipe on remote server or pdc, optionally
 890  * providing domain info
 891  * 
 892  * @param ctx initialised libnet context
 893  * @param mem_ctx memory context of this call
 894  * @param r data structure containing necessary parameters and return values
 895  * @return composite context of this call
 896  **/
 897 
 898 struct composite_context* libnet_RpcConnect_send(struct libnet_context *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 899                                                  TALLOC_CTX *mem_ctx,
 900                                                  struct libnet_RpcConnect *r,
 901                                                  void (*monitor)(struct monitor_msg*))
 902 {
 903         struct composite_context *c;
 904 
 905         switch (r->level) {
 906         case LIBNET_RPC_CONNECT_SERVER:
 907         case LIBNET_RPC_CONNECT_SERVER_ADDRESS:
 908         case LIBNET_RPC_CONNECT_BINDING:
 909                 c = libnet_RpcConnectSrv_send(ctx, mem_ctx, r, monitor);
 910                 break;
 911 
 912         case LIBNET_RPC_CONNECT_PDC:
 913         case LIBNET_RPC_CONNECT_DC:
 914                 c = libnet_RpcConnectDC_send(ctx, mem_ctx, r, monitor);
 915                 break;
 916 
 917         case LIBNET_RPC_CONNECT_DC_INFO:
 918                 c = libnet_RpcConnectDCInfo_send(ctx, mem_ctx, r, monitor);
 919                 break;
 920 
 921         default:
 922                 c = talloc_zero(mem_ctx, struct composite_context);
 923                 composite_error(c, NT_STATUS_INVALID_LEVEL);
 924         }
 925 
 926         return c;
 927 }
 928 
 929 
 930 /**
 931  * Receives result of connection to rpc pipe on remote server or pdc
 932  *
 933  * @param c composite context
 934  * @param ctx initialised libnet context
 935  * @param mem_ctx memory context of this call
 936  * @param r data structure containing necessary parameters and return values
 937  * @return nt status of rpc connection
 938  **/
 939 
 940 NTSTATUS libnet_RpcConnect_recv(struct composite_context *c, struct libnet_context *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 941                                 TALLOC_CTX *mem_ctx, struct libnet_RpcConnect *r)
 942 {
 943         switch (r->level) {
 944         case LIBNET_RPC_CONNECT_SERVER:
 945         case LIBNET_RPC_CONNECT_BINDING:
 946                 return libnet_RpcConnectSrv_recv(c, ctx, mem_ctx, r);
 947 
 948         case LIBNET_RPC_CONNECT_PDC:
 949         case LIBNET_RPC_CONNECT_DC:
 950                 return libnet_RpcConnectDC_recv(c, ctx, mem_ctx, r);
 951 
 952         case LIBNET_RPC_CONNECT_DC_INFO:
 953                 return libnet_RpcConnectDCInfo_recv(c, ctx, mem_ctx, r);
 954 
 955         default:
 956                 ZERO_STRUCT(r->out);
 957                 return NT_STATUS_INVALID_LEVEL;
 958         }
 959 }
 960 
 961 
 962 /**
 963  * Connect to a rpc pipe on a remote server - sync version
 964  *
 965  * @param ctx initialised libnet context
 966  * @param mem_ctx memory context of this call
 967  * @param r data structure containing necessary parameters and return values
 968  * @return nt status of rpc connection
 969  **/
 970 
 971 NTSTATUS libnet_RpcConnect(struct libnet_context *ctx, TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 972                            struct libnet_RpcConnect *r)
 973 {
 974         struct composite_context *c;
 975         
 976         c = libnet_RpcConnect_send(ctx, mem_ctx, r, NULL);
 977         return libnet_RpcConnect_recv(c, ctx, mem_ctx, r);
 978 }

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