root/source4/libnet/libnet_domain.c

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

DEFINITIONS

This source file includes following definitions.
  1. continue_domain_open_rpc_connect
  2. continue_domain_open_close
  3. continue_domain_open_connect
  4. continue_domain_open_lookup
  5. continue_domain_open_open
  6. libnet_DomainOpenSamr_send
  7. libnet_DomainOpenSamr_recv
  8. libnet_DomainOpenLsa_send
  9. continue_rpc_connect_lsa
  10. continue_lsa_policy_open
  11. libnet_DomainOpenLsa_recv
  12. libnet_DomainOpen_send
  13. libnet_DomainOpen_recv
  14. libnet_DomainOpen
  15. libnet_DomainCloseLsa_send
  16. continue_lsa_close
  17. libnet_DomainCloseLsa_recv
  18. libnet_DomainCloseSamr_send
  19. continue_samr_close
  20. libnet_DomainCloseSamr_recv
  21. libnet_DomainClose_send
  22. libnet_DomainClose_recv
  23. libnet_DomainClose
  24. continue_rpc_connect
  25. continue_samr_connect
  26. continue_samr_enum_domains
  27. continue_samr_close_handle
  28. get_domain_list
  29. libnet_DomainList_send
  30. libnet_DomainList_recv
  31. libnet_DomainList

   1 /* 
   2    Unix SMB/CIFS implementation.
   3 
   4    Copyright (C) Rafal Szczesniak 2005
   5    
   6    This program is free software; you can redistribute it and/or modify
   7    it under the terms of the GNU General Public License as published by
   8    the Free Software Foundation; either version 3 of the License, or
   9    (at your option) any later version.
  10    
  11    This program is distributed in the hope that it will be useful,
  12    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14    GNU General Public License for more details.
  15    
  16    You should have received a copy of the GNU General Public License
  17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  18 */
  19 
  20 /*
  21   a composite function for domain handling on samr and lsa pipes
  22 */
  23 
  24 #include "includes.h"
  25 #include "libcli/composite/composite.h"
  26 #include "libnet/libnet.h"
  27 #include "librpc/gen_ndr/ndr_samr_c.h"
  28 #include "librpc/gen_ndr/ndr_lsa_c.h"
  29 
  30 
  31 struct domain_open_samr_state {
  32         struct libnet_context     *ctx;
  33         struct dcerpc_pipe        *pipe;
  34         struct libnet_RpcConnect  rpcconn;
  35         struct samr_Connect       connect;
  36         struct samr_LookupDomain  lookup;
  37         struct samr_OpenDomain    open;
  38         struct samr_Close         close;
  39         struct lsa_String         domain_name;
  40         uint32_t                  access_mask;
  41         struct policy_handle      connect_handle;
  42         struct policy_handle      domain_handle;
  43         struct dom_sid2           *domain_sid;
  44 
  45         /* information about the progress */
  46         void (*monitor_fn)(struct monitor_msg*);
  47 };
  48 
  49 
  50 static void continue_domain_open_close(struct rpc_request *req);
  51 static void continue_domain_open_connect(struct rpc_request *req);
  52 static void continue_domain_open_lookup(struct rpc_request *req);
  53 static void continue_domain_open_open(struct rpc_request *req);
  54 
  55 
  56 /**
  57  * Stage 0.5 (optional): Connect to samr rpc pipe
  58  */
  59 static void continue_domain_open_rpc_connect(struct composite_context *ctx)
     /* [<][>][^][v][top][bottom][index][help] */
  60 {
  61         struct composite_context *c;
  62         struct domain_open_samr_state *s;
  63         struct rpc_request *conn_req;
  64 
  65         c = talloc_get_type(ctx->async.private_data, struct composite_context);
  66         s = talloc_get_type(c->private_data, struct domain_open_samr_state);
  67 
  68         c->status = libnet_RpcConnect_recv(ctx, s->ctx, c, &s->rpcconn);
  69         if (!composite_is_ok(c)) return;
  70 
  71         s->pipe = s->rpcconn.out.dcerpc_pipe;
  72 
  73         /* preparing parameters for samr_Connect rpc call */
  74         s->connect.in.system_name      = 0;
  75         s->connect.in.access_mask      = s->access_mask;
  76         s->connect.out.connect_handle  = &s->connect_handle;
  77 
  78         /* send request */
  79         conn_req = dcerpc_samr_Connect_send(s->pipe, c, &s->connect);
  80         if (composite_nomem(conn_req, c)) return;
  81 
  82         /* callback handler */
  83         composite_continue_rpc(c, conn_req, continue_domain_open_connect, c);
  84 }
  85 
  86 
  87 /**
  88  * Stage 0.5 (optional): Close existing (in libnet context) domain
  89  * handle
  90  */
  91 static void continue_domain_open_close(struct rpc_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
  92 {
  93         struct composite_context *c;
  94         struct domain_open_samr_state *s;
  95         struct rpc_request *conn_req;
  96 
  97         c = talloc_get_type(req->async.private_data, struct composite_context);
  98         s = talloc_get_type(c->private_data, struct domain_open_samr_state);
  99 
 100         /* receive samr_Close reply */
 101         c->status = dcerpc_ndr_request_recv(req);
 102         if (!composite_is_ok(c)) return;
 103 
 104         if (s->monitor_fn) {
 105                 struct monitor_msg msg;
 106                 
 107                 msg.type = mon_SamrClose;
 108                 msg.data = NULL;
 109                 msg.data_size = 0;
 110                 s->monitor_fn(&msg);
 111         }
 112 
 113         /* reset domain handle and associated data in libnet_context */
 114         s->ctx->samr.name        = NULL;
 115         s->ctx->samr.access_mask = 0;
 116         ZERO_STRUCT(s->ctx->samr.handle);
 117 
 118         /* preparing parameters for samr_Connect rpc call */
 119         s->connect.in.system_name      = 0;
 120         s->connect.in.access_mask      = s->access_mask;
 121         s->connect.out.connect_handle  = &s->connect_handle;
 122         
 123         /* send request */
 124         conn_req = dcerpc_samr_Connect_send(s->pipe, c, &s->connect);
 125         if (composite_nomem(conn_req, c)) return;
 126 
 127         /* callback handler */
 128         composite_continue_rpc(c, conn_req, continue_domain_open_connect, c);
 129 }
 130 
 131 
 132 /**
 133  * Stage 1: Connect to SAM server.
 134  */
 135 static void continue_domain_open_connect(struct rpc_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
 136 {
 137         struct composite_context *c;
 138         struct domain_open_samr_state *s;
 139         struct rpc_request *lookup_req;
 140         struct samr_LookupDomain *r;
 141         
 142         c = talloc_get_type(req->async.private_data, struct composite_context);
 143         s = talloc_get_type(c->private_data, struct domain_open_samr_state);
 144 
 145         /* receive samr_Connect reply */
 146         c->status = dcerpc_ndr_request_recv(req);
 147         if (!composite_is_ok(c)) return;
 148 
 149         if (s->monitor_fn) {
 150                 struct monitor_msg msg;
 151 
 152                 msg.type = mon_SamrConnect;
 153                 msg.data = NULL;
 154                 msg.data_size = 0;
 155                 s->monitor_fn(&msg);
 156         }
 157 
 158         r = &s->lookup;
 159 
 160         /* prepare for samr_LookupDomain call */
 161         r->in.connect_handle = &s->connect_handle;
 162         r->in.domain_name    = &s->domain_name;
 163         r->out.sid           = talloc(s, struct dom_sid2 *);
 164         if (composite_nomem(r->out.sid, c)) return;
 165 
 166         lookup_req = dcerpc_samr_LookupDomain_send(s->pipe, c, r);
 167         if (composite_nomem(lookup_req, c)) return;
 168 
 169         composite_continue_rpc(c, lookup_req, continue_domain_open_lookup, c);
 170 }
 171 
 172 
 173 /**
 174  * Stage 2: Lookup domain by name.
 175  */
 176 static void continue_domain_open_lookup(struct rpc_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
 177 {
 178         struct composite_context *c;
 179         struct domain_open_samr_state *s;
 180         struct rpc_request *opendom_req;
 181         struct samr_OpenDomain *r;
 182 
 183         c = talloc_get_type(req->async.private_data, struct composite_context);
 184         s = talloc_get_type(c->private_data, struct domain_open_samr_state);
 185         
 186         /* receive samr_LookupDomain reply */
 187         c->status = dcerpc_ndr_request_recv(req);
 188 
 189         if (s->monitor_fn) {
 190                 struct monitor_msg msg;
 191                 struct msg_rpc_lookup_domain data;
 192 
 193                 data.domain_name = s->domain_name.string;
 194 
 195                 msg.type = mon_SamrLookupDomain;
 196                 msg.data = (void*)&data;
 197                 msg.data_size = sizeof(data);
 198                 s->monitor_fn(&msg);
 199         }
 200 
 201         r = &s->open;
 202 
 203         /* check the rpc layer status */
 204         if (!composite_is_ok(c));
 205 
 206         /* check the rpc call itself status */
 207         if (!NT_STATUS_IS_OK(s->lookup.out.result)) {
 208                 composite_error(c, s->lookup.out.result);
 209                 return;
 210         }
 211 
 212         /* prepare for samr_OpenDomain call */
 213         r->in.connect_handle = &s->connect_handle;
 214         r->in.access_mask    = SEC_FLAG_MAXIMUM_ALLOWED;
 215         r->in.sid            = *s->lookup.out.sid;
 216         r->out.domain_handle = &s->domain_handle;
 217 
 218         opendom_req = dcerpc_samr_OpenDomain_send(s->pipe, c, r);
 219         if (composite_nomem(opendom_req, c)) return;
 220 
 221         composite_continue_rpc(c, opendom_req, continue_domain_open_open, c);
 222 }
 223 
 224 
 225 /*
 226  * Stage 3: Open domain.
 227  */
 228 static void continue_domain_open_open(struct rpc_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
 229 {
 230         struct composite_context *c;
 231         struct domain_open_samr_state *s;
 232 
 233         c = talloc_get_type(req->async.private_data, struct composite_context);
 234         s = talloc_get_type(c->private_data, struct domain_open_samr_state);
 235 
 236         /* receive samr_OpenDomain reply */
 237         c->status = dcerpc_ndr_request_recv(req);
 238         if (!composite_is_ok(c)) return;
 239 
 240         if (s->monitor_fn) {
 241                 struct monitor_msg msg;
 242                 
 243                 msg.type = mon_SamrOpenDomain;
 244                 msg.data = NULL;
 245                 msg.data_size = 0;
 246                 s->monitor_fn(&msg);
 247         }
 248 
 249         composite_done(c);
 250 }
 251 
 252 
 253 /**
 254  * Sends asynchronous DomainOpenSamr request
 255  *
 256  * @param ctx initialised libnet context
 257  * @param io arguments and results of the call
 258  * @param monitor pointer to monitor function that is passed monitor message
 259  */
 260 
 261 struct composite_context *libnet_DomainOpenSamr_send(struct libnet_context *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 262                                                      struct libnet_DomainOpen *io,
 263                                                      void (*monitor)(struct monitor_msg*))
 264 {
 265         struct composite_context *c;
 266         struct domain_open_samr_state *s;
 267         struct composite_context *rpcconn_req;
 268         struct rpc_request *close_req, *conn_req;
 269 
 270         c = composite_create(ctx, ctx->event_ctx);
 271         if (c == NULL) return NULL;
 272 
 273         s = talloc_zero(c, struct domain_open_samr_state);
 274         if (composite_nomem(s, c)) return c;
 275 
 276         c->private_data = s;
 277         s->monitor_fn   = monitor;
 278 
 279         s->ctx                 = ctx;
 280         s->pipe                = ctx->samr.pipe;
 281         s->access_mask         = io->in.access_mask;
 282         s->domain_name.string  = talloc_strdup(c, io->in.domain_name);
 283 
 284         /* check, if there's samr pipe opened already, before opening a domain */
 285         if (ctx->samr.pipe == NULL) {
 286 
 287                 /* attempting to connect a domain controller */
 288                 s->rpcconn.level           = LIBNET_RPC_CONNECT_DC;
 289                 s->rpcconn.in.name         = io->in.domain_name;
 290                 s->rpcconn.in.dcerpc_iface = &ndr_table_samr;
 291                 
 292                 /* send rpc pipe connect request */
 293                 rpcconn_req = libnet_RpcConnect_send(ctx, c, &s->rpcconn, s->monitor_fn);
 294                 if (composite_nomem(rpcconn_req, c)) return c;
 295 
 296                 composite_continue(c, rpcconn_req, continue_domain_open_rpc_connect, c);
 297                 return c;
 298         }
 299 
 300         /* libnet context's domain handle is not empty, so check out what
 301            was opened first, before doing anything */
 302         if (!policy_handle_empty(&ctx->samr.handle)) {
 303                 if (strequal(ctx->samr.name, io->in.domain_name) &&
 304                     ctx->samr.access_mask == io->in.access_mask) {
 305 
 306                         /* this domain is already opened */
 307                         composite_done(c);
 308                         return c;
 309 
 310                 } else {
 311                         /* another domain or access rights have been
 312                            requested - close the existing handle first */
 313                         s->close.in.handle = &ctx->samr.handle;
 314 
 315                         /* send request to close domain handle */
 316                         close_req = dcerpc_samr_Close_send(s->pipe, c, &s->close);
 317                         if (composite_nomem(close_req, c)) return c;
 318 
 319                         /* callback handler */
 320                         composite_continue_rpc(c, close_req, continue_domain_open_close, c);
 321                         return c;
 322                 }
 323         }
 324 
 325         /* preparing parameters for samr_Connect rpc call */
 326         s->connect.in.system_name      = 0;
 327         s->connect.in.access_mask      = s->access_mask;
 328         s->connect.out.connect_handle  = &s->connect_handle;
 329         
 330         /* send request */
 331         conn_req = dcerpc_samr_Connect_send(s->pipe, c, &s->connect);
 332         if (composite_nomem(conn_req, c)) return c;
 333 
 334         /* callback handler */
 335         composite_continue_rpc(c, conn_req, continue_domain_open_connect, c);
 336         return c;
 337 }
 338 
 339 
 340 /**
 341  * Waits for and receives result of asynchronous DomainOpenSamr call
 342  * 
 343  * @param c composite context returned by asynchronous DomainOpen call
 344  * @param ctx initialised libnet context
 345  * @param mem_ctx memory context of the call
 346  * @param io pointer to results (and arguments) of the call
 347  * @return nt status code of execution
 348  */
 349 
 350 NTSTATUS libnet_DomainOpenSamr_recv(struct composite_context *c, struct libnet_context *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 351                                     TALLOC_CTX *mem_ctx, struct libnet_DomainOpen *io)
 352 {
 353         NTSTATUS status;
 354         struct domain_open_samr_state *s;
 355 
 356         /* wait for results of sending request */
 357         status = composite_wait(c);
 358         
 359         if (NT_STATUS_IS_OK(status) && io) {
 360                 s = talloc_get_type(c->private_data, struct domain_open_samr_state);
 361                 io->out.domain_handle = s->domain_handle;
 362 
 363                 /* store the resulting handle and related data for use by other
 364                    libnet functions */
 365                 ctx->samr.connect_handle = s->connect_handle;
 366                 ctx->samr.handle      = s->domain_handle;
 367                 ctx->samr.sid         = talloc_steal(ctx, *s->lookup.out.sid);
 368                 ctx->samr.name        = talloc_steal(ctx, s->domain_name.string);
 369                 ctx->samr.access_mask = s->access_mask;
 370         }
 371 
 372         talloc_free(c);
 373         return status;
 374 }
 375 
 376 
 377 struct domain_open_lsa_state {
 378         const char *name;
 379         uint32_t access_mask;
 380         struct libnet_context *ctx;
 381         struct libnet_RpcConnect rpcconn;
 382         struct lsa_OpenPolicy2   openpol;
 383         struct policy_handle handle;
 384         struct dcerpc_pipe *pipe;
 385 
 386         /* information about the progress */
 387         void (*monitor_fn)(struct monitor_msg*);
 388 };
 389 
 390 
 391 static void continue_rpc_connect_lsa(struct composite_context *ctx);
 392 static void continue_lsa_policy_open(struct rpc_request *req);
 393 
 394 
 395 /**
 396  * Sends asynchronous DomainOpenLsa request
 397  *
 398  * @param ctx initialised libnet context
 399  * @param io arguments and results of the call
 400  * @param monitor pointer to monitor function that is passed monitor message
 401  */
 402 
 403 struct composite_context* libnet_DomainOpenLsa_send(struct libnet_context *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 404                                                     struct libnet_DomainOpen *io,
 405                                                     void (*monitor)(struct monitor_msg*))
 406 {
 407         struct composite_context *c;
 408         struct domain_open_lsa_state *s;
 409         struct composite_context *rpcconn_req;
 410         struct rpc_request *openpol_req;
 411         struct lsa_QosInfo *qos;
 412 
 413         /* create composite context and state */
 414         c = composite_create(ctx, ctx->event_ctx);
 415         if (c == NULL) return c;
 416 
 417         s = talloc_zero(c, struct domain_open_lsa_state);
 418         if (composite_nomem(s, c)) return c;
 419 
 420         c->private_data = s;
 421 
 422         /* store arguments in the state structure */
 423         s->name         = talloc_strdup(c, io->in.domain_name);
 424         s->access_mask  = io->in.access_mask;
 425         s->ctx          = ctx;
 426 
 427         /* check, if there's lsa pipe opened already, before opening a handle */
 428         if (ctx->lsa.pipe == NULL) {
 429 
 430                 /* attempting to connect a domain controller */
 431                 s->rpcconn.level           = LIBNET_RPC_CONNECT_DC;
 432                 s->rpcconn.in.name         = talloc_strdup(c, io->in.domain_name);
 433                 s->rpcconn.in.dcerpc_iface = &ndr_table_lsarpc;
 434                 
 435                 /* send rpc pipe connect request */
 436                 rpcconn_req = libnet_RpcConnect_send(ctx, c, &s->rpcconn, s->monitor_fn);
 437                 if (composite_nomem(rpcconn_req, c)) return c;
 438 
 439                 composite_continue(c, rpcconn_req, continue_rpc_connect_lsa, c);
 440                 return c;
 441         }
 442 
 443         s->pipe = ctx->lsa.pipe;
 444 
 445         /* preparing parameters for lsa_OpenPolicy2 rpc call */
 446         s->openpol.in.system_name = s->name;
 447         s->openpol.in.access_mask = s->access_mask;
 448         s->openpol.in.attr        = talloc_zero(c, struct lsa_ObjectAttribute);
 449 
 450         qos = talloc_zero(c, struct lsa_QosInfo);
 451         qos->len                 = 0;
 452         qos->impersonation_level = 2;
 453         qos->context_mode        = 1;
 454         qos->effective_only      = 0;
 455 
 456         s->openpol.in.attr->sec_qos = qos;
 457         s->openpol.out.handle       = &s->handle;
 458         
 459         /* send rpc request */
 460         openpol_req = dcerpc_lsa_OpenPolicy2_send(s->pipe, c, &s->openpol);
 461         if (composite_nomem(openpol_req, c)) return c;
 462 
 463         composite_continue_rpc(c, openpol_req, continue_lsa_policy_open, c);
 464         return c;
 465 }
 466 
 467 
 468 /*
 469   Stage 0.5 (optional): Rpc pipe connected, send lsa open policy request
 470  */
 471 static void continue_rpc_connect_lsa(struct composite_context *ctx)
     /* [<][>][^][v][top][bottom][index][help] */
 472 {
 473         struct composite_context *c;
 474         struct domain_open_lsa_state *s;
 475         struct lsa_QosInfo *qos;
 476         struct rpc_request *openpol_req;
 477 
 478         c = talloc_get_type(ctx->async.private_data, struct composite_context);
 479         s = talloc_get_type(c->private_data, struct domain_open_lsa_state);
 480 
 481         /* receive rpc connection */
 482         c->status = libnet_RpcConnect_recv(ctx, s->ctx, c, &s->rpcconn);
 483         if (!composite_is_ok(c)) return;
 484 
 485         /* RpcConnect function leaves the pipe in libnet context,
 486            so get it from there */
 487         s->pipe = s->ctx->lsa.pipe;
 488 
 489         /* prepare lsa_OpenPolicy2 call */
 490         s->openpol.in.system_name = s->name;
 491         s->openpol.in.access_mask = s->access_mask;
 492         s->openpol.in.attr        = talloc_zero(c, struct lsa_ObjectAttribute);
 493 
 494         qos = talloc_zero(c, struct lsa_QosInfo);
 495         qos->len                 = 0;
 496         qos->impersonation_level = 2;
 497         qos->context_mode        = 1;
 498         qos->effective_only      = 0;
 499 
 500         s->openpol.in.attr->sec_qos = qos;
 501         s->openpol.out.handle       = &s->handle;
 502 
 503         /* send rpc request */
 504         openpol_req = dcerpc_lsa_OpenPolicy2_send(s->pipe, c, &s->openpol);
 505         if (composite_nomem(openpol_req, c)) return;
 506 
 507         composite_continue_rpc(c, openpol_req, continue_lsa_policy_open, c);
 508 }
 509 
 510 
 511 /*
 512   Stage 1: Lsa policy opened - we're done, if successfully
 513  */
 514 static void continue_lsa_policy_open(struct rpc_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
 515 {
 516         struct composite_context *c;
 517         struct domain_open_lsa_state *s;
 518 
 519         c = talloc_get_type(req->async.private_data, struct composite_context);
 520         s = talloc_get_type(c->private_data, struct domain_open_lsa_state);
 521 
 522         c->status = dcerpc_ndr_request_recv(req);
 523         if (!composite_is_ok(c)) return;
 524 
 525         if (s->monitor_fn) {
 526                 struct monitor_msg msg;
 527                 
 528                 msg.type      = mon_LsaOpenPolicy;
 529                 msg.data      = NULL;
 530                 msg.data_size = 0;
 531                 s->monitor_fn(&msg);
 532         }
 533 
 534         composite_done(c);
 535 }
 536 
 537 
 538 /**
 539  * Receives result of asynchronous DomainOpenLsa call
 540  *
 541  * @param c composite context returned by asynchronous DomainOpenLsa call
 542  * @param ctx initialised libnet context
 543  * @param mem_ctx memory context of the call
 544  * @param io pointer to results (and arguments) of the call
 545  * @return nt status code of execution
 546  */
 547 
 548 NTSTATUS libnet_DomainOpenLsa_recv(struct composite_context *c, struct libnet_context *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 549                                    TALLOC_CTX *mem_ctx, struct libnet_DomainOpen *io)
 550 {
 551         NTSTATUS status;
 552         struct domain_open_lsa_state *s;
 553 
 554         status = composite_wait(c);
 555 
 556         if (NT_STATUS_IS_OK(status) && io) {
 557                 /* everything went fine - get the results and
 558                    return the error string */
 559                 s = talloc_get_type(c->private_data, struct domain_open_lsa_state);
 560                 io->out.domain_handle = s->handle;
 561 
 562                 ctx->lsa.handle      = s->handle;
 563                 ctx->lsa.name        = talloc_steal(ctx, s->name);
 564                 ctx->lsa.access_mask = s->access_mask;
 565                 
 566                 io->out.error_string = talloc_strdup(mem_ctx, "Success");
 567 
 568         } else if (!NT_STATUS_IS_OK(status)) {
 569                 /* there was an error, so provide nt status code description */
 570                 io->out.error_string = talloc_asprintf(mem_ctx,
 571                                                        "Failed to open domain: %s",
 572                                                        nt_errstr(status));
 573         }
 574 
 575         talloc_free(c);
 576         return status;
 577 }
 578 
 579 
 580 /**
 581  * Sends a request to open a domain in desired service
 582  *
 583  * @param ctx initalised libnet context
 584  * @param io arguments and results of the call
 585  * @param monitor pointer to monitor function that is passed monitor message
 586  */
 587 
 588 struct composite_context* libnet_DomainOpen_send(struct libnet_context *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 589                                                  struct libnet_DomainOpen *io,
 590                                                  void (*monitor)(struct monitor_msg*))
 591 {
 592         struct composite_context *c;
 593 
 594         switch (io->in.type) {
 595         case DOMAIN_LSA:
 596                 /* reques to open a policy handle on \pipe\lsarpc */
 597                 c = libnet_DomainOpenLsa_send(ctx, io, monitor);
 598                 break;
 599 
 600         case DOMAIN_SAMR:
 601         default:
 602                 /* request to open a domain policy handle on \pipe\samr */
 603                 c = libnet_DomainOpenSamr_send(ctx, io, monitor);
 604                 break;
 605         }
 606 
 607         return c;
 608 }
 609 
 610 
 611 /**
 612  * Receive result of domain open request
 613  *
 614  * @param c composite context returned by DomainOpen_send function
 615  * @param ctx initialised libnet context
 616  * @param mem_ctx memory context of the call
 617  * @param io results and arguments of the call
 618  */
 619 
 620 NTSTATUS libnet_DomainOpen_recv(struct composite_context *c, struct libnet_context *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 621                                 TALLOC_CTX *mem_ctx, struct libnet_DomainOpen *io)
 622 {
 623         NTSTATUS status;
 624 
 625         switch (io->in.type) {
 626         case DOMAIN_LSA:
 627                 status = libnet_DomainOpenLsa_recv(c, ctx, mem_ctx, io);
 628                 break;
 629 
 630         case DOMAIN_SAMR:
 631         default:
 632                 status = libnet_DomainOpenSamr_recv(c, ctx, mem_ctx, io);
 633                 break;
 634         }
 635         
 636         return status;
 637 }
 638 
 639 
 640 /**
 641  * Synchronous version of DomainOpen call
 642  *
 643  * @param ctx initialised libnet context
 644  * @param mem_ctx memory context for the call
 645  * @param io arguments and results of the call
 646  * @return nt status code of execution
 647  */
 648 
 649 NTSTATUS libnet_DomainOpen(struct libnet_context *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 650                            TALLOC_CTX *mem_ctx,
 651                            struct libnet_DomainOpen *io)
 652 {
 653         struct composite_context *c = libnet_DomainOpen_send(ctx, io, NULL);
 654         return libnet_DomainOpen_recv(c, ctx, mem_ctx, io);
 655 }
 656 
 657 
 658 struct domain_close_lsa_state {
 659         struct dcerpc_pipe *pipe;
 660         struct lsa_Close close;
 661         struct policy_handle handle;
 662 
 663         void (*monitor_fn)(struct monitor_msg*);
 664 };
 665 
 666 
 667 static void continue_lsa_close(struct rpc_request *req);
 668 
 669 
 670 struct composite_context* libnet_DomainCloseLsa_send(struct libnet_context *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 671                                                      struct libnet_DomainClose *io,
 672                                                      void (*monitor)(struct monitor_msg*))
 673 {
 674         struct composite_context *c;
 675         struct domain_close_lsa_state *s;
 676         struct rpc_request *close_req;
 677 
 678         /* composite context and state structure allocation */
 679         c = composite_create(ctx, ctx->event_ctx);
 680         if (c == NULL) return c;
 681 
 682         s = talloc_zero(c, struct domain_close_lsa_state);
 683         if (composite_nomem(s, c)) return c;
 684 
 685         c->private_data = s;
 686         s->monitor_fn   = monitor;
 687 
 688         /* TODO: check if lsa pipe pointer is non-null */
 689 
 690         if (!strequal(ctx->lsa.name, io->in.domain_name)) {
 691                 composite_error(c, NT_STATUS_INVALID_PARAMETER);
 692                 return c;
 693         }
 694 
 695         /* get opened lsarpc pipe pointer */
 696         s->pipe = ctx->lsa.pipe;
 697         
 698         /* prepare close handle call arguments */
 699         s->close.in.handle  = &ctx->lsa.handle;
 700         s->close.out.handle = &s->handle;
 701 
 702         /* send the request */
 703         close_req = dcerpc_lsa_Close_send(s->pipe, c, &s->close);
 704         if (composite_nomem(close_req, c)) return c;
 705 
 706         composite_continue_rpc(c, close_req, continue_lsa_close, c);
 707         return c;
 708 }
 709 
 710 
 711 /*
 712   Stage 1: Receive result of lsa close call
 713 */
 714 static void continue_lsa_close(struct rpc_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
 715 {
 716         struct composite_context *c;
 717         struct domain_close_lsa_state *s;
 718         
 719         c = talloc_get_type(req->async.private_data, struct composite_context);
 720         s = talloc_get_type(c->private_data, struct domain_close_lsa_state);
 721 
 722         c->status = dcerpc_ndr_request_recv(req);
 723         if (!composite_is_ok(c)) return;
 724 
 725         if (s->monitor_fn) {
 726                 struct monitor_msg msg;
 727 
 728                 msg.type      = mon_LsaClose;
 729                 msg.data      = NULL;
 730                 msg.data_size = 0;
 731                 s->monitor_fn(&msg);
 732         }
 733 
 734         composite_done(c);
 735 }
 736 
 737 
 738 NTSTATUS libnet_DomainCloseLsa_recv(struct composite_context *c, struct libnet_context *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 739                                     TALLOC_CTX *mem_ctx, struct libnet_DomainClose *io)
 740 {
 741         NTSTATUS status;
 742 
 743         status = composite_wait(c);
 744 
 745         if (NT_STATUS_IS_OK(status) && io) {
 746                 /* policy handle closed successfully */
 747 
 748                 ctx->lsa.name = NULL;
 749                 ZERO_STRUCT(ctx->lsa.handle);
 750 
 751                 io->out.error_string = talloc_asprintf(mem_ctx, "Success");
 752 
 753         } else if (!NT_STATUS_IS_OK(status)) {
 754                 /* there was an error, so return description of the status code */
 755                 io->out.error_string = talloc_asprintf(mem_ctx, "Error: %s", nt_errstr(status));
 756         }
 757 
 758         talloc_free(c);
 759         return status;
 760 }
 761 
 762 
 763 struct domain_close_samr_state {
 764         struct samr_Close close;
 765         struct policy_handle handle;
 766         
 767         void (*monitor_fn)(struct monitor_msg*);
 768 };
 769 
 770 
 771 static void continue_samr_close(struct rpc_request *req);
 772 
 773 
 774 struct composite_context* libnet_DomainCloseSamr_send(struct libnet_context *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 775                                                       struct libnet_DomainClose *io,
 776                                                       void (*monitor)(struct monitor_msg*))
 777 {
 778         struct composite_context *c;
 779         struct domain_close_samr_state *s;
 780         struct rpc_request *close_req;
 781 
 782         /* composite context and state structure allocation */
 783         c = composite_create(ctx, ctx->event_ctx);
 784         if (c == NULL) return c;
 785 
 786         s = talloc_zero(c, struct domain_close_samr_state);
 787         if (composite_nomem(s, c)) return c;
 788 
 789         c->private_data = s;
 790         s->monitor_fn   = monitor;
 791 
 792         /* TODO: check if samr pipe pointer is non-null */
 793 
 794         if (!strequal(ctx->samr.name, io->in.domain_name)) {
 795                 composite_error(c, NT_STATUS_INVALID_PARAMETER);
 796                 return c;
 797         }
 798 
 799         /* prepare close domain handle call arguments */
 800         ZERO_STRUCT(s->close);
 801         s->close.in.handle  = &ctx->samr.handle;
 802         s->close.out.handle = &s->handle;
 803 
 804         /* send the request */
 805         close_req = dcerpc_samr_Close_send(ctx->samr.pipe, ctx, &s->close);
 806         if (composite_nomem(close_req, c)) return c;
 807 
 808         composite_continue_rpc(c, close_req, continue_samr_close, c);
 809         return c;
 810 }
 811 
 812 
 813 /*
 814   Stage 1: Receive result of samr close call
 815 */
 816 static void continue_samr_close(struct rpc_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
 817 {
 818         struct composite_context *c;
 819         struct domain_close_samr_state *s;
 820 
 821         c = talloc_get_type(req->async.private_data, struct composite_context);
 822         s = talloc_get_type(c->private_data, struct domain_close_samr_state);
 823         
 824         c->status = dcerpc_ndr_request_recv(req);
 825         if (!composite_is_ok(c)) return;
 826 
 827         if (s->monitor_fn) {
 828                 struct monitor_msg msg;
 829                 
 830                 msg.type      = mon_SamrClose;
 831                 msg.data      = NULL;
 832                 msg.data_size = 0;
 833                 s->monitor_fn(&msg);
 834         }
 835         
 836         composite_done(c);
 837 }
 838 
 839 
 840 NTSTATUS libnet_DomainCloseSamr_recv(struct composite_context *c, struct libnet_context *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 841                                      TALLOC_CTX *mem_ctx, struct libnet_DomainClose *io)
 842 {
 843         NTSTATUS status;
 844 
 845         status = composite_wait(c);
 846 
 847         if (NT_STATUS_IS_OK(status) && io) {
 848                 /* domain policy handle closed successfully */
 849 
 850                 ZERO_STRUCT(ctx->samr.handle);
 851                 talloc_free(discard_const_p(char, ctx->samr.name));
 852                 talloc_free(ctx->samr.sid);
 853                 ctx->samr.name = NULL;
 854                 ctx->samr.sid = NULL;
 855 
 856                 io->out.error_string = talloc_asprintf(mem_ctx, "Success");
 857 
 858         } else if (!NT_STATUS_IS_OK(status)) {
 859                 /* there was an error, so return description of the status code */
 860                 io->out.error_string = talloc_asprintf(mem_ctx, "Error: %s", nt_errstr(status));
 861         }
 862 
 863         talloc_free(c);
 864         return status;
 865 }
 866 
 867 
 868 struct composite_context* libnet_DomainClose_send(struct libnet_context *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 869                                                   struct libnet_DomainClose *io,
 870                                                   void (*monitor)(struct monitor_msg*))
 871 {
 872         struct composite_context *c;
 873 
 874         switch (io->in.type) {
 875         case DOMAIN_LSA:
 876                 /* request to close policy handle on \pipe\lsarpc */
 877                 c = libnet_DomainCloseLsa_send(ctx, io, monitor);
 878                 break;
 879 
 880         case DOMAIN_SAMR:
 881         default:
 882                 /* request to close domain policy handle on \pipe\samr */
 883                 c = libnet_DomainCloseSamr_send(ctx, io, monitor);
 884                 break;
 885         }
 886         
 887         return c;
 888 }
 889 
 890 
 891 NTSTATUS libnet_DomainClose_recv(struct composite_context *c, struct libnet_context *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 892                                  TALLOC_CTX *mem_ctx, struct libnet_DomainClose *io)
 893 {
 894         NTSTATUS status;
 895 
 896         switch (io->in.type) {
 897         case DOMAIN_LSA:
 898                 /* receive result of closing lsa policy handle */
 899                 status = libnet_DomainCloseLsa_recv(c, ctx, mem_ctx, io);
 900                 break;
 901 
 902         case DOMAIN_SAMR:
 903         default:
 904                 /* receive result of closing samr domain policy handle */
 905                 status = libnet_DomainCloseSamr_recv(c, ctx, mem_ctx, io);
 906                 break;
 907         }
 908         
 909         return status;
 910 }
 911 
 912 
 913 NTSTATUS libnet_DomainClose(struct libnet_context *ctx, TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 914                             struct libnet_DomainClose *io)
 915 {
 916         struct composite_context *c;
 917         
 918         c = libnet_DomainClose_send(ctx, io, NULL);
 919         return libnet_DomainClose_recv(c, ctx, mem_ctx, io);
 920 }
 921 
 922 
 923 struct domain_list_state {      
 924         struct libnet_context *ctx;
 925         struct libnet_RpcConnect rpcconn;
 926         struct samr_Connect samrconn;
 927         struct samr_EnumDomains enumdom;
 928         struct samr_Close samrclose;
 929         const char *hostname;
 930         struct policy_handle connect_handle;
 931         int buf_size;
 932         struct domainlist *domains;
 933         uint32_t resume_handle;
 934         uint32_t count;
 935 
 936         void (*monitor_fn)(struct monitor_msg*);
 937 };
 938 
 939 
 940 static void continue_rpc_connect(struct composite_context *c);
 941 static void continue_samr_connect(struct rpc_request *c);
 942 static void continue_samr_enum_domains(struct rpc_request *req);
 943 static void continue_samr_close_handle(struct rpc_request *req);
 944 
 945 static struct domainlist* get_domain_list(TALLOC_CTX *mem_ctx, struct domain_list_state *s);
 946 
 947 
 948 /*
 949   Stage 1: Receive connected rpc pipe and send connection
 950   request to SAMR service
 951 */
 952 static void continue_rpc_connect(struct composite_context *ctx)
     /* [<][>][^][v][top][bottom][index][help] */
 953 {
 954         struct composite_context *c;
 955         struct domain_list_state *s;
 956         struct rpc_request *samrconn_req;
 957 
 958         c = talloc_get_type(ctx->async.private_data, struct composite_context);
 959         s = talloc_get_type(c->private_data, struct domain_list_state);
 960         
 961         c->status = libnet_RpcConnect_recv(ctx, s->ctx, c, &s->rpcconn);
 962         if (!composite_is_ok(c)) return;
 963 
 964         s->samrconn.in.system_name     = 0;
 965         s->samrconn.in.access_mask     = SEC_GENERIC_READ;     /* should be enough */
 966         s->samrconn.out.connect_handle = &s->connect_handle;
 967 
 968         samrconn_req = dcerpc_samr_Connect_send(s->ctx->samr.pipe, c, &s->samrconn);
 969         if (composite_nomem(samrconn_req, c)) return;
 970 
 971         composite_continue_rpc(c, samrconn_req, continue_samr_connect, c);
 972 }
 973 
 974 
 975 /*
 976   Stage 2: Receive policy handle to the connected SAMR service and issue
 977   a request to enumerate domain databases available
 978 */
 979 static void continue_samr_connect(struct rpc_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
 980 {
 981         struct composite_context *c;
 982         struct domain_list_state *s;
 983         struct rpc_request *enumdom_req;
 984 
 985         c = talloc_get_type(req->async.private_data, struct composite_context);
 986         s = talloc_get_type(c->private_data, struct domain_list_state);
 987         
 988         c->status = dcerpc_ndr_request_recv(req);
 989         if (!composite_is_ok(c)) return;
 990 
 991         if (s->monitor_fn) {
 992                 struct monitor_msg msg;
 993                 
 994                 msg.type      = mon_SamrConnect;
 995                 msg.data      = NULL;
 996                 msg.data_size = 0;
 997                 s->monitor_fn(&msg);
 998         }
 999 
1000         s->enumdom.in.connect_handle = &s->connect_handle;
1001         s->enumdom.in.resume_handle  = &s->resume_handle;
1002         s->enumdom.in.buf_size       = s->buf_size;
1003         s->enumdom.out.resume_handle = &s->resume_handle;
1004         s->enumdom.out.num_entries   = talloc(s, uint32_t);
1005         if (composite_nomem(s->enumdom.out.num_entries, c)) return;
1006         s->enumdom.out.sam           = talloc(s, struct samr_SamArray *);
1007         if (composite_nomem(s->enumdom.out.sam, c)) return;
1008 
1009         enumdom_req = dcerpc_samr_EnumDomains_send(s->ctx->samr.pipe, c, &s->enumdom);
1010         if (composite_nomem(enumdom_req, c)) return;
1011 
1012         composite_continue_rpc(c, enumdom_req, continue_samr_enum_domains, c);
1013 }
1014 
1015 
1016 /*
1017   Stage 3: Receive domain names available and repeat the request
1018   enumeration is not complete yet. Close samr connection handle
1019   upon completion.
1020 */
1021 static void continue_samr_enum_domains(struct rpc_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
1022 {
1023         struct composite_context *c;
1024         struct domain_list_state *s;
1025         struct rpc_request *enumdom_req;
1026         struct rpc_request *samrclose_req;
1027 
1028         c = talloc_get_type(req->async.private_data, struct composite_context);
1029         s = talloc_get_type(c->private_data, struct domain_list_state);
1030         
1031         c->status = dcerpc_ndr_request_recv(req);
1032         if (!composite_is_ok(c)) return;
1033 
1034         if (s->monitor_fn) {
1035                 struct monitor_msg msg;
1036                 
1037                 msg.type      = mon_SamrEnumDomains;
1038                 msg.data      = NULL;
1039                 msg.data_size = 0;
1040                 s->monitor_fn(&msg);
1041         }
1042 
1043         if (NT_STATUS_IS_OK(s->enumdom.out.result)) {
1044 
1045                 s->domains = get_domain_list(c, s);
1046 
1047         } else if (NT_STATUS_EQUAL(s->enumdom.out.result, STATUS_MORE_ENTRIES)) {
1048                 
1049                 s->domains = get_domain_list(c, s);
1050                 
1051                 /* prepare next round of enumeration */
1052                 s->enumdom.in.connect_handle = &s->connect_handle;
1053                 s->enumdom.in.resume_handle  = &s->resume_handle;
1054                 s->enumdom.in.buf_size       = s->ctx->samr.buf_size;
1055                 s->enumdom.out.resume_handle = &s->resume_handle;
1056 
1057                 /* send the request */
1058                 enumdom_req = dcerpc_samr_EnumDomains_send(s->ctx->samr.pipe, c, &s->enumdom);
1059                 if (composite_nomem(enumdom_req, c)) return;
1060 
1061                 composite_continue_rpc(c, enumdom_req, continue_samr_enum_domains, c);
1062 
1063         } else {
1064                 composite_error(c, s->enumdom.out.result);
1065                 return;
1066         }
1067 
1068         /* close samr connection handle */
1069         s->samrclose.in.handle  = &s->connect_handle;
1070         s->samrclose.out.handle = &s->connect_handle;
1071         
1072         /* send the request */
1073         samrclose_req = dcerpc_samr_Close_send(s->ctx->samr.pipe, c, &s->samrclose);
1074         if (composite_nomem(samrclose_req, c)) return;
1075 
1076         composite_continue_rpc(c, samrclose_req, continue_samr_close_handle, c);
1077 }
1078 
1079 
1080 /*
1081   Stage 4: Receive result of closing samr connection handle.
1082 */
1083 static void continue_samr_close_handle(struct rpc_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
1084 {
1085         struct composite_context *c;
1086         struct domain_list_state *s;
1087 
1088         c = talloc_get_type(req->async.private_data, struct composite_context);
1089         s = talloc_get_type(c->private_data, struct domain_list_state);
1090 
1091         c->status = dcerpc_ndr_request_recv(req);
1092         if (!composite_is_ok(c)) return;
1093 
1094         if (s->monitor_fn) {
1095                 struct monitor_msg msg;
1096                 
1097                 msg.type      = mon_SamrClose;
1098                 msg.data      = NULL;
1099                 msg.data_size = 0;
1100                 s->monitor_fn(&msg);
1101         }
1102 
1103         /* did everything go fine ? */
1104         if (!NT_STATUS_IS_OK(s->samrclose.out.result)) {
1105                 composite_error(c, s->samrclose.out.result);
1106         }
1107 
1108         composite_done(c);
1109 }
1110 
1111 
1112 /*
1113   Utility function to copy domain names from result of samr_EnumDomains call
1114 */
1115 static struct domainlist* get_domain_list(TALLOC_CTX *mem_ctx, struct domain_list_state *s)
     /* [<][>][^][v][top][bottom][index][help] */
1116 {
1117         int i;
1118         if (mem_ctx == NULL || s == NULL) return NULL;
1119 
1120         /* prepare domains array */
1121         if (s->domains == NULL) {
1122                 s->domains = talloc_array(mem_ctx, struct domainlist,
1123                                           *s->enumdom.out.num_entries);
1124         } else {
1125                 s->domains = talloc_realloc(mem_ctx, s->domains, struct domainlist,
1126                                             s->count + *s->enumdom.out.num_entries);
1127         }
1128 
1129         /* copy domain names returned from samr_EnumDomains call */
1130         for (i = s->count; i < s->count + *s->enumdom.out.num_entries; i++)
1131         {
1132                 struct lsa_String *domain_name = &(*s->enumdom.out.sam)->entries[i - s->count].name;
1133 
1134                 /* strdup name as a child of allocated array to make it follow the array
1135                    in case of talloc_steal or talloc_free */
1136                 s->domains[i].name = talloc_strdup(s->domains, domain_name->string);
1137                 s->domains[i].sid  = NULL;  /* this is to be filled out later */
1138         }
1139 
1140         /* number of entries returned (domains enumerated) */
1141         s->count += *s->enumdom.out.num_entries;
1142         
1143         return s->domains;
1144 }
1145 
1146 
1147 /**
1148  * Sends a request to list domains on given host
1149  *
1150  * @param ctx initalised libnet context
1151  * @param mem_ctx memory context
1152  * @param io arguments and results of the call
1153  * @param monitor pointer to monitor function that is passed monitor messages
1154  */
1155 
1156 struct composite_context* libnet_DomainList_send(struct libnet_context *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
1157                                                  TALLOC_CTX *mem_ctx,
1158                                                  struct libnet_DomainList *io,
1159                                                  void (*monitor)(struct monitor_msg*))
1160 {
1161         struct composite_context *c;
1162         struct domain_list_state *s;
1163         struct composite_context *rpcconn_req;
1164         struct rpc_request *samrconn_req;
1165 
1166         /* composite context and state structure allocation */
1167         c = composite_create(ctx, ctx->event_ctx);
1168         if (c == NULL) return c;
1169 
1170         s = talloc_zero(c, struct domain_list_state);
1171         if (composite_nomem(s, c)) return c;
1172 
1173         c->private_data = s;
1174         s->monitor_fn   = monitor;
1175 
1176         s->ctx      = ctx;
1177         s->hostname = talloc_strdup(c, io->in.hostname);
1178         if (composite_nomem(s->hostname, c)) return c;
1179 
1180         /* check whether samr pipe has already been opened */
1181         if (ctx->samr.pipe == NULL) {
1182                 /* prepare rpc connect call */
1183                 s->rpcconn.level           = LIBNET_RPC_CONNECT_SERVER;
1184                 s->rpcconn.in.name         = s->hostname;
1185                 s->rpcconn.in.dcerpc_iface = &ndr_table_samr;
1186 
1187                 rpcconn_req = libnet_RpcConnect_send(ctx, c, &s->rpcconn, s->monitor_fn);
1188                 if (composite_nomem(rpcconn_req, c)) return c;
1189                 
1190                 composite_continue(c, rpcconn_req, continue_rpc_connect, c);
1191 
1192         } else {
1193                 /* prepare samr_Connect call */
1194                 s->samrconn.in.system_name     = 0;
1195                 s->samrconn.in.access_mask     = SEC_GENERIC_READ;
1196                 s->samrconn.out.connect_handle = &s->connect_handle;
1197                 
1198                 samrconn_req = dcerpc_samr_Connect_send(s->ctx->samr.pipe, c, &s->samrconn);
1199                 if (composite_nomem(samrconn_req, c)) return c;
1200 
1201                 composite_continue_rpc(c, samrconn_req, continue_samr_connect, c);
1202         }
1203 
1204         return c;
1205 }
1206 
1207 
1208 /**
1209  * Receive result of domain list request
1210  *
1211  * @param c composite context returned by DomainList_send function
1212  * @param ctx initialised libnet context
1213  * @param mem_ctx memory context of the call
1214  * @param io results and arguments of the call
1215  */
1216 
1217 NTSTATUS libnet_DomainList_recv(struct composite_context *c, struct libnet_context *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
1218                                 TALLOC_CTX *mem_ctx, struct libnet_DomainList *io)
1219 {
1220         NTSTATUS status;
1221         struct domain_list_state *s;
1222 
1223         status = composite_wait(c);
1224 
1225         s = talloc_get_type(c->private_data, struct domain_list_state);
1226 
1227         if (NT_STATUS_IS_OK(status) && ctx && mem_ctx && io) {
1228                 /* fetch the results to be returned by io structure */
1229                 io->out.count        = s->count;
1230                 io->out.domains      = talloc_steal(mem_ctx, s->domains);
1231                 io->out.error_string = talloc_asprintf(mem_ctx, "Success");
1232 
1233         } else if (!NT_STATUS_IS_OK(status)) {
1234                 /* there was an error, so return description of the status code */
1235                 io->out.error_string = talloc_asprintf(mem_ctx, "Error: %s", nt_errstr(status));
1236         }
1237 
1238         talloc_free(c);
1239         return status;
1240 }
1241 
1242 
1243 /**
1244  * Synchronous version of DomainList call
1245  *
1246  * @param ctx initialised libnet context
1247  * @param mem_ctx memory context for the call
1248  * @param io arguments and results of the call
1249  * @return nt status code of execution
1250  */
1251 
1252 NTSTATUS libnet_DomainList(struct libnet_context *ctx, TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
1253                            struct libnet_DomainList *io)
1254 {
1255         struct composite_context *c;
1256 
1257         c = libnet_DomainList_send(ctx, mem_ctx, io, NULL);
1258         return libnet_DomainList_recv(c, ctx, mem_ctx, io);
1259 }

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