Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : async lookupsids
4 : Copyright (C) Volker Lendecke 2011
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 : #include "includes.h"
21 : #include "winbindd.h"
22 : #include "lib/util_unixsids.h"
23 : #include "librpc/gen_ndr/ndr_winbind_c.h"
24 : #include "../libcli/security/security.h"
25 : #include "passdb/machine_sid.h"
26 : #include "lsa.h"
27 :
28 : struct wb_lookupsids_domain {
29 : struct winbindd_domain *domain;
30 :
31 : /*
32 : * Array of sids to be passed into wbint_LookupSids. Preallocated with
33 : * num_sids.
34 : */
35 : struct lsa_SidArray sids;
36 :
37 : /*
38 : * Indexes into wb_lookupsids_state->sids and thus
39 : * wb_lookupsids_state->res_names. Preallocated with num_sids.
40 : */
41 : uint32_t *sid_indexes;
42 : };
43 :
44 : struct wb_translated_name {
45 : const char *domain_name;
46 : const char *name;
47 : enum lsa_SidType type;
48 : };
49 :
50 : static struct wb_lookupsids_domain *wb_lookupsids_get_domain(
51 : const struct dom_sid *sid, TALLOC_CTX *mem_ctx,
52 : struct wb_lookupsids_domain **domains, uint32_t num_sids);
53 :
54 : struct wb_lookupsids_state {
55 : struct tevent_context *ev;
56 :
57 : /*
58 : * SIDs passed in
59 : */
60 : struct dom_sid *sids;
61 : uint32_t num_sids;
62 :
63 : /*
64 : * The domains we're using for bulk lookup via wbint_LookupRids or
65 : * wbint_LookupSids. We expect very few domains, so we do a
66 : * talloc_realloc and rely on talloc_array_length.
67 : */
68 : struct wb_lookupsids_domain *domains;
69 : uint32_t domains_done;
70 :
71 : /*
72 : * These SIDs are looked up individually via
73 : * wbint_LookupSid. Preallocated with num_sids.
74 : */
75 : uint32_t *single_sids;
76 : uint32_t num_single_sids;
77 : uint32_t single_sids_done;
78 :
79 : /*
80 : * Intermediate store for wbint_LookupRids to passdb. These are
81 : * spliced into res_domains/res_names in wb_lookupsids_move_name.
82 : */
83 : struct wbint_RidArray rids;
84 : const char *domain_name;
85 : struct wbint_Principals rid_names;
86 :
87 : /*
88 : * Intermediate results for wbint_LookupSids. These results are
89 : * spliced into res_domains/res_names in wb_lookupsids_move_name.
90 : */
91 : struct lsa_RefDomainList tmp_domains;
92 : struct lsa_TransNameArray tmp_names;
93 :
94 : /*
95 : * Results
96 : */
97 : struct lsa_RefDomainList *res_domains;
98 : /*
99 : * Indexed as "sids" in this structure
100 : */
101 : struct lsa_TransNameArray *res_names;
102 : };
103 :
104 : static bool wb_lookupsids_next(struct tevent_req *req,
105 : struct wb_lookupsids_state *state);
106 : static void wb_lookupsids_single_done(struct tevent_req *subreq);
107 : static void wb_lookupsids_lookuprids_done(struct tevent_req *subreq);
108 : static void wb_lookupsids_done(struct tevent_req *subreq);
109 :
110 2094 : struct tevent_req *wb_lookupsids_send(TALLOC_CTX *mem_ctx,
111 : struct tevent_context *ev,
112 : struct dom_sid *sids,
113 : uint32_t num_sids)
114 : {
115 0 : struct tevent_req *req;
116 0 : struct wb_lookupsids_state *state;
117 0 : uint32_t i;
118 :
119 2094 : req = tevent_req_create(mem_ctx, &state, struct wb_lookupsids_state);
120 2094 : if (req == NULL) {
121 0 : return NULL;
122 : }
123 :
124 2094 : D_INFO("WB command lookupsids start.\nLooking up %"PRIu32" SID(s)\n",
125 : num_sids);
126 2094 : if (CHECK_DEBUGLVL(DBGLVL_INFO)) {
127 0 : for (i = 0; i < num_sids; i++) {
128 0 : struct dom_sid_buf buf;
129 0 : D_INFO("%"PRIu32": %s\n",
130 : i, dom_sid_str_buf(&sids[i], &buf));
131 : }
132 : }
133 :
134 2094 : state->ev = ev;
135 2094 : state->sids = sids;
136 2094 : state->num_sids = num_sids;
137 :
138 2094 : state->single_sids = talloc_zero_array(state, uint32_t, num_sids);
139 2094 : if (tevent_req_nomem(state->single_sids, req)) {
140 0 : return tevent_req_post(req, ev);
141 : }
142 :
143 2094 : state->res_domains = talloc_zero(state, struct lsa_RefDomainList);
144 2094 : if (tevent_req_nomem(state->res_domains, req)) {
145 0 : return tevent_req_post(req, ev);
146 : }
147 2094 : state->res_domains->domains = talloc_zero_array(
148 : state->res_domains, struct lsa_DomainInfo, num_sids);
149 2094 : if (tevent_req_nomem(state->res_domains->domains, req)) {
150 0 : return tevent_req_post(req, ev);
151 : }
152 :
153 2094 : state->res_names = talloc_zero(state, struct lsa_TransNameArray);
154 2094 : if (tevent_req_nomem(state->res_names, req)) {
155 0 : return tevent_req_post(req, ev);
156 : }
157 2094 : state->res_names->names = talloc_zero_array(
158 : state->res_names, struct lsa_TranslatedName, num_sids);
159 2094 : if (tevent_req_nomem(state->res_names->names, req)) {
160 0 : return tevent_req_post(req, ev);
161 : }
162 :
163 2094 : if (num_sids == 0) {
164 638 : tevent_req_done(req);
165 638 : return tevent_req_post(req, ev);
166 : }
167 :
168 3426 : for (i=0; i<num_sids; i++) {
169 0 : struct wb_lookupsids_domain *d;
170 :
171 1970 : d = wb_lookupsids_get_domain(&sids[i], state, &state->domains,
172 : num_sids);
173 1970 : if (d != NULL) {
174 1234 : d->sids.sids[d->sids.num_sids].sid = &sids[i];
175 1234 : d->sid_indexes[d->sids.num_sids] = i;
176 1234 : d->sids.num_sids += 1;
177 : } else {
178 736 : state->single_sids[state->num_single_sids] = i;
179 736 : state->num_single_sids += 1;
180 : }
181 : }
182 :
183 1456 : if (!wb_lookupsids_next(req, state)) {
184 0 : return tevent_req_post(req, ev);
185 : }
186 1456 : return req;
187 : }
188 :
189 2626 : static bool wb_lookupsids_next(struct tevent_req *req,
190 : struct wb_lookupsids_state *state)
191 : {
192 0 : struct tevent_req *subreq;
193 :
194 2626 : if (state->domains_done < talloc_array_length(state->domains)) {
195 0 : struct wb_lookupsids_domain *d;
196 0 : uint32_t i;
197 :
198 1162 : d = &state->domains[state->domains_done];
199 :
200 1162 : if (d->domain->internal) {
201 : /*
202 : * This is only our local SAM,
203 : * see wb_lookupsids_bulk() and
204 : * wb_lookupsids_get_domain().
205 : */
206 2 : state->rids.num_rids = d->sids.num_sids;
207 2 : state->rids.rids = talloc_array(state, uint32_t,
208 : state->rids.num_rids);
209 2 : if (tevent_req_nomem(state->rids.rids, req)) {
210 0 : return false;
211 : }
212 4 : for (i=0; i<state->rids.num_rids; i++) {
213 2 : sid_peek_rid(d->sids.sids[i].sid,
214 2 : &state->rids.rids[i]);
215 : }
216 2 : subreq = dcerpc_wbint_LookupRids_send(
217 : state, state->ev, dom_child_handle(d->domain),
218 2 : &d->domain->sid, &state->rids, &state->domain_name,
219 : &state->rid_names);
220 2 : if (tevent_req_nomem(subreq, req)) {
221 0 : return false;
222 : }
223 2 : tevent_req_set_callback(
224 : subreq, wb_lookupsids_lookuprids_done, req);
225 2 : return true;
226 : }
227 :
228 1160 : subreq = dcerpc_wbint_LookupSids_send(
229 : state, state->ev, dom_child_handle(d->domain),
230 : &d->sids, &state->tmp_domains, &state->tmp_names);
231 1160 : if (tevent_req_nomem(subreq, req)) {
232 0 : return false;
233 : }
234 1160 : tevent_req_set_callback(subreq, wb_lookupsids_done, req);
235 1160 : return true;
236 : }
237 :
238 1464 : if (state->single_sids_done < state->num_single_sids) {
239 0 : uint32_t sid_idx;
240 0 : const struct dom_sid *sid;
241 :
242 736 : sid_idx = state->single_sids[state->single_sids_done];
243 736 : sid = &state->sids[sid_idx];
244 :
245 736 : subreq = wb_lookupsid_send(state, state->ev, sid);
246 736 : if (tevent_req_nomem(subreq, req)) {
247 0 : return false;
248 : }
249 736 : tevent_req_set_callback(subreq, wb_lookupsids_single_done,
250 : req);
251 736 : return true;
252 : }
253 :
254 728 : tevent_req_done(req);
255 728 : return false;
256 : }
257 :
258 : /*
259 : * Decide whether to do bulk lookupsids. We have optimizations for
260 : * passdb via lookuprids and to remote DCs via lookupsids.
261 : */
262 :
263 1970 : static bool wb_lookupsids_bulk(const struct dom_sid *sid)
264 : {
265 0 : struct dom_sid_buf sidbuf;
266 :
267 1970 : if (sid->num_auths != 5) {
268 : /*
269 : * Only do "S-1-5-21-x-y-z-rid" domains via bulk
270 : * lookup
271 : */
272 736 : DBG_DEBUG("No bulk setup for SID %s with %"PRIi8" subauths\n",
273 : dom_sid_str_buf(sid, &sidbuf),
274 : sid->num_auths);
275 736 : return false;
276 : }
277 :
278 1234 : if (sid_check_is_in_our_sam(sid)) {
279 : /*
280 : * Passdb lookup via lookuprids
281 : */
282 2 : DBG_DEBUG("%s is in our domain\n",
283 : dom_sid_str_buf(sid, &sidbuf));
284 2 : return true;
285 : }
286 :
287 1232 : if (IS_DC) {
288 : /*
289 : * Bulk lookups to trusted DCs
290 : */
291 4 : return (find_domain_from_sid_noinit(sid) != NULL);
292 : }
293 :
294 1228 : if (lp_server_role() != ROLE_DOMAIN_MEMBER) {
295 : /*
296 : * Don't do bulk lookups as standalone, the only bulk
297 : * lookup left is for domain members.
298 : */
299 0 : return false;
300 : }
301 :
302 2456 : if (sid_check_is_in_unix_groups(sid) ||
303 2456 : sid_check_is_unix_groups(sid) ||
304 2456 : sid_check_is_in_unix_users(sid) ||
305 2456 : sid_check_is_unix_users(sid) ||
306 2456 : sid_check_is_in_builtin(sid) ||
307 2456 : sid_check_is_builtin(sid) ||
308 2456 : sid_check_is_wellknown_domain(sid, NULL) ||
309 1228 : sid_check_is_in_wellknown_domain(sid))
310 : {
311 : /*
312 : * These are locally done piece by piece anyway, no
313 : * need for bulk optimizations.
314 : */
315 0 : return false;
316 : }
317 :
318 : /*
319 : * All other SIDs are sent to the DC we're connected to as
320 : * member via a single lsa_lookupsids call.
321 : */
322 1228 : return true;
323 : }
324 :
325 1970 : static struct wb_lookupsids_domain *wb_lookupsids_get_domain(
326 : const struct dom_sid *sid, TALLOC_CTX *mem_ctx,
327 : struct wb_lookupsids_domain **pdomains, uint32_t num_sids)
328 : {
329 0 : struct wb_lookupsids_domain *domains, *domain;
330 0 : struct winbindd_domain *wb_domain;
331 0 : uint32_t i, num_domains;
332 :
333 1970 : if (!wb_lookupsids_bulk(sid)) {
334 736 : D_DEBUG("wb_lookupsids_bulk() is FALSE\n");
335 736 : return NULL;
336 : }
337 1234 : D_DEBUG("wb_lookupsids_bulk() is TRUE\n");
338 :
339 1234 : domains = *pdomains;
340 1234 : num_domains = talloc_array_length(domains);
341 :
342 1234 : wb_domain = find_lookup_domain_from_sid(sid);
343 1234 : if (wb_domain == NULL) {
344 0 : return NULL;
345 : }
346 :
347 1234 : D_DEBUG("Searching %"PRIu32" domain(s) for domain '%s'\n",
348 : num_domains, wb_domain->name);
349 1239 : for (i=0; i<num_domains; i++) {
350 77 : if (domains[i].domain != wb_domain) {
351 5 : continue;
352 : }
353 :
354 72 : if (!domains[i].domain->internal) {
355 : /*
356 : * If it's not our local sam,
357 : * we can re-use the domain without
358 : * checking the sid.
359 : *
360 : * Note the wb_lookupsids_bulk() above
361 : * already caught special SIDs,
362 : * e.g. the unix and builtin domains.
363 : */
364 72 : return &domains[i];
365 : }
366 :
367 0 : if (dom_sid_compare_domain(sid, &domains[i].domain->sid) == 0) {
368 : /*
369 : * If it's out local sam we can also use it.
370 : */
371 0 : return &domains[i];
372 : }
373 :
374 : /*
375 : * I'm not sure if this can be triggered,
376 : * as wb_lookupsids_bulk() should also catch this,
377 : * but we need to make sure that we don't use
378 : * wbint_LookupRids() without a SID match.
379 : */
380 0 : return NULL;
381 : }
382 :
383 1162 : domains = talloc_realloc(
384 : mem_ctx, domains, struct wb_lookupsids_domain, num_domains+1);
385 1162 : if (domains == NULL) {
386 0 : return NULL;
387 : }
388 1162 : *pdomains = domains;
389 :
390 1162 : domain = &domains[num_domains];
391 1162 : domain->domain = wb_domain;
392 :
393 1162 : domain->sids.sids = talloc_zero_array(domains, struct lsa_SidPtr, num_sids);
394 1162 : if (domains->sids.sids == NULL) {
395 0 : goto fail;
396 : }
397 1162 : domain->sids.num_sids = 0;
398 :
399 1162 : domain->sid_indexes = talloc_zero_array(domains, uint32_t, num_sids);
400 1162 : if (domain->sid_indexes == NULL) {
401 0 : TALLOC_FREE(domain->sids.sids);
402 0 : goto fail;
403 : }
404 1162 : return domain;
405 :
406 0 : fail:
407 : /*
408 : * Realloc to the state it was in before
409 : */
410 0 : *pdomains = talloc_realloc(
411 : mem_ctx, domains, struct wb_lookupsids_domain, num_domains);
412 0 : return NULL;
413 : }
414 :
415 788 : static bool wb_lookupsids_find_dom_idx(struct lsa_DomainInfo *domain,
416 : struct lsa_RefDomainList *list,
417 : uint32_t *idx)
418 : {
419 0 : uint32_t i;
420 0 : struct lsa_DomainInfo *new_domain;
421 :
422 793 : for (i=0; i<list->count; i++) {
423 65 : if (dom_sid_equal(domain->sid, list->domains[i].sid)) {
424 60 : *idx = i;
425 60 : return true;
426 : }
427 : }
428 :
429 728 : new_domain = &list->domains[list->count];
430 :
431 1456 : new_domain->name.string = talloc_strdup(
432 728 : list->domains, domain->name.string);
433 728 : if (new_domain->name.string == NULL) {
434 0 : return false;
435 : }
436 :
437 728 : new_domain->sid = dom_sid_dup(list->domains, domain->sid);
438 728 : if (new_domain->sid == NULL) {
439 0 : return false;
440 : }
441 :
442 728 : *idx = list->count;
443 728 : list->count += 1;
444 728 : return true;
445 : }
446 :
447 1242 : static bool wb_lookupsids_move_name(struct lsa_RefDomainList *src_domains,
448 : struct lsa_TranslatedName *src_name,
449 : struct lsa_RefDomainList *dst_domains,
450 : struct lsa_TransNameArray *dst_names,
451 : uint32_t dst_name_index)
452 : {
453 0 : struct lsa_TranslatedName *dst_name;
454 0 : struct lsa_DomainInfo *src_domain;
455 0 : uint32_t src_domain_index;
456 1242 : uint32_t dst_domain_index = UINT32_MAX;
457 0 : bool ok;
458 :
459 1242 : src_domain_index = src_name->sid_index;
460 1242 : if ((src_domain_index != UINT32_MAX) && (src_domains != NULL)) {
461 788 : if (src_domain_index >= src_domains->count) {
462 0 : return false;
463 : }
464 788 : src_domain = &src_domains->domains[src_domain_index];
465 :
466 788 : ok = wb_lookupsids_find_dom_idx(src_domain,
467 : dst_domains,
468 : &dst_domain_index);
469 788 : if (!ok) {
470 0 : return false;
471 : }
472 : }
473 :
474 1242 : dst_name = &dst_names->names[dst_name_index];
475 :
476 1242 : dst_name->sid_type = src_name->sid_type;
477 1242 : dst_name->name.string = talloc_move(dst_names->names,
478 : &src_name->name.string);
479 1242 : dst_name->sid_index = dst_domain_index;
480 1242 : dst_names->count += 1;
481 :
482 1242 : return true;
483 : }
484 :
485 1160 : static void wb_lookupsids_done(struct tevent_req *subreq)
486 : {
487 1160 : struct tevent_req *req = tevent_req_callback_data(
488 : subreq, struct tevent_req);
489 1160 : struct wb_lookupsids_state *state = tevent_req_data(
490 : req, struct wb_lookupsids_state);
491 0 : struct wb_lookupsids_domain *d;
492 0 : uint32_t i;
493 :
494 0 : NTSTATUS status, result;
495 :
496 1160 : status = dcerpc_wbint_LookupSids_recv(subreq, state, &result);
497 1160 : TALLOC_FREE(subreq);
498 1160 : if (tevent_req_nterror(req, status)) {
499 0 : return;
500 : }
501 1160 : if (NT_STATUS_LOOKUP_ERR(result)) {
502 0 : tevent_req_nterror(req, result);
503 0 : return;
504 : }
505 :
506 : /*
507 : * Look at the individual states in the translated names.
508 : */
509 :
510 1160 : d = &state->domains[state->domains_done];
511 :
512 2392 : for (i=0; i<state->tmp_names.count; i++) {
513 1232 : uint32_t res_sid_index = d->sid_indexes[i];
514 :
515 1232 : if (!wb_lookupsids_move_name(
516 1232 : &state->tmp_domains, &state->tmp_names.names[i],
517 : state->res_domains, state->res_names,
518 : res_sid_index)) {
519 0 : tevent_req_oom(req);
520 0 : return;
521 : }
522 : }
523 1160 : state->domains_done += 1;
524 1160 : wb_lookupsids_next(req, state);
525 : }
526 :
527 736 : static void wb_lookupsids_single_done(struct tevent_req *subreq)
528 : {
529 736 : struct tevent_req *req = tevent_req_callback_data(
530 : subreq, struct tevent_req);
531 736 : struct wb_lookupsids_state *state = tevent_req_data(
532 : req, struct wb_lookupsids_state);
533 736 : const char *domain_name = NULL;
534 736 : const char *name = NULL;
535 736 : enum lsa_SidType type = SID_NAME_UNKNOWN;
536 0 : uint32_t res_sid_index;
537 0 : uint32_t src_rid;
538 :
539 0 : struct dom_sid src_domain_sid;
540 0 : struct lsa_DomainInfo src_domain;
541 0 : struct lsa_RefDomainList src_domains;
542 736 : struct lsa_RefDomainList *psrc_domains = NULL;
543 0 : struct lsa_TranslatedName src_name;
544 :
545 736 : uint32_t domain_idx = UINT32_MAX;
546 0 : NTSTATUS status;
547 0 : bool ok;
548 :
549 736 : status = wb_lookupsid_recv(subreq, talloc_tos(), &type,
550 : &domain_name, &name);
551 736 : TALLOC_FREE(subreq);
552 736 : if (NT_STATUS_LOOKUP_ERR(status)) {
553 728 : tevent_req_nterror(req, status);
554 728 : return;
555 : }
556 :
557 8 : res_sid_index = state->single_sids[state->single_sids_done];
558 :
559 8 : if ((domain_name != NULL) && (domain_name[0] != '\0')) {
560 : /*
561 : * Build structs with the domain name for
562 : * wb_lookupsids_move_name(). If we didn't get a name, we will
563 : * pass NULL and UINT32_MAX.
564 : */
565 :
566 6 : sid_copy(&src_domain_sid, &state->sids[res_sid_index]);
567 6 : if (type != SID_NAME_DOMAIN) {
568 0 : sid_split_rid(&src_domain_sid, &src_rid);
569 : }
570 :
571 6 : src_domain.name.string = domain_name;
572 6 : src_domain.sid = &src_domain_sid;
573 :
574 6 : src_domains.count = 1;
575 6 : src_domains.domains = &src_domain;
576 6 : psrc_domains = &src_domains;
577 :
578 6 : domain_idx = 0;
579 : }
580 :
581 8 : src_name.sid_type = type;
582 8 : src_name.name.string = name;
583 8 : src_name.sid_index = domain_idx;
584 :
585 8 : ok = wb_lookupsids_move_name(psrc_domains,
586 : &src_name,
587 : state->res_domains,
588 : state->res_names,
589 : res_sid_index);
590 8 : if (!ok) {
591 0 : tevent_req_oom(req);
592 0 : return;
593 : }
594 8 : state->single_sids_done += 1;
595 8 : wb_lookupsids_next(req, state);
596 : }
597 :
598 2 : static void wb_lookupsids_lookuprids_done(struct tevent_req *subreq)
599 : {
600 2 : struct tevent_req *req = tevent_req_callback_data(
601 : subreq, struct tevent_req);
602 2 : struct wb_lookupsids_state *state = tevent_req_data(
603 : req, struct wb_lookupsids_state);
604 0 : struct dom_sid src_domain_sid;
605 0 : struct lsa_DomainInfo src_domain;
606 0 : struct lsa_RefDomainList src_domains;
607 0 : NTSTATUS status, result;
608 0 : struct wb_lookupsids_domain *d;
609 0 : uint32_t i;
610 :
611 2 : status = dcerpc_wbint_LookupRids_recv(subreq, state, &result);
612 2 : TALLOC_FREE(subreq);
613 2 : if (tevent_req_nterror(req, status)) {
614 0 : return;
615 : }
616 2 : if (NT_STATUS_LOOKUP_ERR(result)) {
617 0 : tevent_req_nterror(req, result);
618 0 : return;
619 : }
620 :
621 : /*
622 : * Look at the individual states in the translated names.
623 : */
624 :
625 2 : d = &state->domains[state->domains_done];
626 :
627 2 : sid_copy(&src_domain_sid, get_global_sam_sid());
628 2 : src_domain.name.string = get_global_sam_name();
629 2 : src_domain.sid = &src_domain_sid;
630 2 : src_domains.count = 1;
631 2 : src_domains.domains = &src_domain;
632 :
633 4 : for (i=0; i<state->rid_names.num_principals; i++) {
634 0 : struct lsa_TranslatedName src_name;
635 0 : uint32_t res_sid_index;
636 :
637 : /*
638 : * Fake up structs for wb_lookupsids_move_name
639 : */
640 2 : res_sid_index = d->sid_indexes[i];
641 :
642 2 : src_name.sid_type = state->rid_names.principals[i].type;
643 2 : src_name.name.string = state->rid_names.principals[i].name;
644 2 : src_name.sid_index = 0;
645 :
646 2 : if (!wb_lookupsids_move_name(
647 : &src_domains, &src_name,
648 : state->res_domains, state->res_names,
649 : res_sid_index)) {
650 0 : tevent_req_oom(req);
651 0 : return;
652 : }
653 : }
654 :
655 2 : state->domains_done += 1;
656 2 : wb_lookupsids_next(req, state);
657 : }
658 :
659 2094 : NTSTATUS wb_lookupsids_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
660 : struct lsa_RefDomainList **domains,
661 : struct lsa_TransNameArray **names)
662 : {
663 2094 : struct wb_lookupsids_state *state = tevent_req_data(
664 : req, struct wb_lookupsids_state);
665 0 : NTSTATUS status;
666 :
667 2094 : D_INFO("WB command lookupsids end.\n");
668 2094 : if (tevent_req_is_nterror(req, &status)) {
669 728 : D_WARNING("Failed with %s.\n", nt_errstr(status));
670 728 : return status;
671 : }
672 :
673 : /*
674 : * The returned names need to match the given sids,
675 : * if not we have a bug in the code!
676 : */
677 1366 : if (state->res_names->count != state->num_sids) {
678 0 : D_WARNING("Got %"PRIu32" returned name(s), but expected %"PRIu32"!\n",
679 : state->res_names->count, state->num_sids);
680 0 : return NT_STATUS_INTERNAL_ERROR;
681 : }
682 :
683 : /*
684 : * Not strictly needed, but it might make debugging in the callers
685 : * easier in future, if the talloc_array_length() returns the
686 : * expected result...
687 : */
688 1366 : state->res_domains->domains = talloc_realloc(state->res_domains,
689 : state->res_domains->domains,
690 : struct lsa_DomainInfo,
691 : state->res_domains->count);
692 :
693 1366 : *domains = talloc_move(mem_ctx, &state->res_domains);
694 1366 : *names = talloc_move(mem_ctx, &state->res_names);
695 1366 : D_INFO("Returning %"PRIu32" domain(s) and %"PRIu32" name(s).\n",
696 : (*domains)->count,
697 : (*names)->count);
698 1366 : return NT_STATUS_OK;
699 : }
|