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