Line data Source code
1 : /*
2 : * Unix SMB/CIFS implementation.
3 : *
4 : * Winbind rpc backend functions
5 : *
6 : * Copyright (c) 2000-2003 Tim Potter
7 : * Copyright (c) 2001 Andrew Tridgell
8 : * Copyright (c) 2005 Volker Lendecke
9 : * Copyright (c) 2008 Guenther Deschner (pidl conversion)
10 : * Copyright (c) 2010 Andreas Schneider <asn@samba.org>
11 : *
12 : * This program is free software; you can redistribute it and/or modify
13 : * it under the terms of the GNU General Public License as published by
14 : * the Free Software Foundation; either version 3 of the License, or
15 : * (at your option) any later version.
16 : *
17 : * This program is distributed in the hope that it will be useful,
18 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 : * GNU General Public License for more details.
21 : *
22 : * You should have received a copy of the GNU General Public License
23 : * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 : */
25 :
26 : #include "includes.h"
27 : #include "winbindd.h"
28 : #include "winbindd_rpc.h"
29 : #include "rpc_client/rpc_client.h"
30 : #include "librpc/gen_ndr/ndr_samr_c.h"
31 : #include "librpc/gen_ndr/ndr_lsa_c.h"
32 : #include "rpc_client/cli_samr.h"
33 : #include "rpc_client/cli_lsarpc.h"
34 : #include "../libcli/security/security.h"
35 : #include "lsa.h"
36 :
37 : /* Query display info for a domain */
38 0 : NTSTATUS rpc_query_user_list(TALLOC_CTX *mem_ctx,
39 : struct rpc_pipe_client *samr_pipe,
40 : struct policy_handle *samr_policy,
41 : const struct dom_sid *domain_sid,
42 : uint32_t **prids)
43 : {
44 0 : struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
45 0 : uint32_t *rids = NULL;
46 0 : uint32_t num_rids = 0;
47 0 : uint32_t i = 0;
48 0 : uint32_t resume_handle = 0;
49 0 : NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
50 0 : NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
51 : TALLOC_CTX *tmp_ctx;
52 :
53 0 : *prids = NULL;
54 :
55 0 : tmp_ctx = talloc_stackframe();
56 0 : if (tmp_ctx == NULL) {
57 0 : return NT_STATUS_NO_MEMORY;
58 : }
59 :
60 : do {
61 0 : struct samr_SamArray *sam_array = NULL;
62 0 : uint32_t count = 0;
63 : uint32_t *tmp;
64 :
65 0 : status = dcerpc_samr_EnumDomainUsers(
66 : b, tmp_ctx, samr_policy, &resume_handle,
67 : ACB_NORMAL, &sam_array, 0xffff, &count, &result);
68 0 : if (!NT_STATUS_IS_OK(status)) {
69 0 : goto done;
70 : }
71 0 : if (!NT_STATUS_IS_OK(result)) {
72 0 : if (!NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
73 0 : DBG_WARNING("EnumDomainUsers failed: %s\n",
74 : nt_errstr(result));
75 0 : status = result;
76 0 : goto done;
77 : }
78 : }
79 :
80 0 : if (num_rids + count < num_rids) {
81 0 : status = NT_STATUS_INTEGER_OVERFLOW;
82 0 : goto done;
83 : }
84 :
85 0 : tmp = talloc_realloc(tmp_ctx, rids, uint32_t, num_rids+count);
86 0 : if (tmp == NULL) {
87 0 : status = NT_STATUS_NO_MEMORY;
88 0 : goto done;
89 : }
90 0 : rids = tmp;
91 :
92 0 : for (i=0; i<count; i++) {
93 0 : rids[num_rids++] = sam_array->entries[i].idx;
94 : }
95 :
96 0 : TALLOC_FREE(sam_array);
97 0 : } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
98 :
99 0 : *prids = talloc_steal(mem_ctx, rids);
100 0 : status = NT_STATUS_OK;
101 :
102 0 : done:
103 0 : TALLOC_FREE(tmp_ctx);
104 0 : return status;
105 : }
106 :
107 : /* List all domain groups */
108 0 : NTSTATUS rpc_enum_dom_groups(TALLOC_CTX *mem_ctx,
109 : struct rpc_pipe_client *samr_pipe,
110 : struct policy_handle *samr_policy,
111 : uint32_t *pnum_info,
112 : struct wb_acct_info **pinfo)
113 : {
114 0 : struct wb_acct_info *info = NULL;
115 0 : uint32_t start = 0;
116 0 : uint32_t num_info = 0;
117 : NTSTATUS status, result;
118 0 : struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
119 :
120 0 : *pnum_info = 0;
121 :
122 : do {
123 0 : struct samr_SamArray *sam_array = NULL;
124 0 : uint32_t count = 0;
125 : uint32_t g;
126 :
127 : /* start is updated by this call. */
128 0 : status = dcerpc_samr_EnumDomainGroups(b,
129 : mem_ctx,
130 : samr_policy,
131 : &start,
132 : &sam_array,
133 : 0xFFFF, /* buffer size? */
134 : &count,
135 : &result);
136 0 : if (!NT_STATUS_IS_OK(status)) {
137 0 : return status;
138 : }
139 0 : if (!NT_STATUS_IS_OK(result)) {
140 0 : if (!NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
141 0 : DEBUG(2,("query_user_list: failed to enum domain groups: %s\n",
142 : nt_errstr(result)));
143 0 : return result;
144 : }
145 : }
146 :
147 0 : info = talloc_realloc(mem_ctx,
148 : info,
149 : struct wb_acct_info,
150 : num_info + count);
151 0 : if (info == NULL) {
152 0 : return NT_STATUS_NO_MEMORY;
153 : }
154 :
155 0 : for (g = 0; g < count; g++) {
156 0 : struct wb_acct_info *i = &info[num_info + g];
157 :
158 0 : i->acct_name = talloc_strdup(info,
159 0 : sam_array->entries[g].name.string);
160 0 : if (i->acct_name == NULL) {
161 0 : TALLOC_FREE(info);
162 0 : return NT_STATUS_NO_MEMORY;
163 : }
164 0 : i->acct_desc = NULL;
165 0 : i->rid = sam_array->entries[g].idx;
166 : }
167 :
168 0 : num_info += count;
169 0 : } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
170 :
171 0 : *pnum_info = num_info;
172 0 : *pinfo = info;
173 :
174 0 : return NT_STATUS_OK;
175 : }
176 :
177 0 : NTSTATUS rpc_enum_local_groups(TALLOC_CTX *mem_ctx,
178 : struct rpc_pipe_client *samr_pipe,
179 : struct policy_handle *samr_policy,
180 : uint32_t *pnum_info,
181 : struct wb_acct_info **pinfo)
182 : {
183 0 : struct wb_acct_info *info = NULL;
184 0 : uint32_t num_info = 0;
185 : NTSTATUS status, result;
186 0 : struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
187 :
188 0 : *pnum_info = 0;
189 :
190 : do {
191 0 : struct samr_SamArray *sam_array = NULL;
192 0 : uint32_t count = 0;
193 0 : uint32_t start = num_info;
194 : uint32_t g;
195 :
196 0 : status = dcerpc_samr_EnumDomainAliases(b,
197 : mem_ctx,
198 : samr_policy,
199 : &start,
200 : &sam_array,
201 : 0xFFFF, /* buffer size? */
202 : &count,
203 : &result);
204 0 : if (!NT_STATUS_IS_OK(status)) {
205 0 : return status;
206 : }
207 0 : if (!NT_STATUS_IS_OK(result)) {
208 0 : if (!NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
209 0 : return result;
210 : }
211 : }
212 :
213 0 : info = talloc_realloc(mem_ctx,
214 : info,
215 : struct wb_acct_info,
216 : num_info + count);
217 0 : if (info == NULL) {
218 0 : return NT_STATUS_NO_MEMORY;
219 : }
220 :
221 0 : for (g = 0; g < count; g++) {
222 0 : struct wb_acct_info *i = &info[num_info + g];
223 :
224 0 : i->acct_name = talloc_strdup(info,
225 0 : sam_array->entries[g].name.string);
226 0 : if (i->acct_name == NULL) {
227 0 : TALLOC_FREE(info);
228 0 : return NT_STATUS_NO_MEMORY;
229 : }
230 0 : i->acct_desc = NULL;
231 0 : i->rid = sam_array->entries[g].idx;
232 : }
233 :
234 0 : num_info += count;
235 0 : } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
236 :
237 0 : *pnum_info = num_info;
238 0 : *pinfo = info;
239 :
240 0 : return NT_STATUS_OK;
241 : }
242 :
243 : /* Lookup groups a user is a member of. */
244 0 : NTSTATUS rpc_lookup_usergroups(TALLOC_CTX *mem_ctx,
245 : struct rpc_pipe_client *samr_pipe,
246 : struct policy_handle *samr_policy,
247 : const struct dom_sid *domain_sid,
248 : const struct dom_sid *user_sid,
249 : uint32_t *pnum_groups,
250 : struct dom_sid **puser_grpsids)
251 : {
252 : struct policy_handle user_policy;
253 0 : struct samr_RidWithAttributeArray *rid_array = NULL;
254 0 : struct dom_sid *user_grpsids = NULL;
255 0 : uint32_t num_groups = 0, i;
256 : uint32_t user_rid;
257 : NTSTATUS status, result;
258 0 : struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
259 :
260 0 : if (!sid_peek_check_rid(domain_sid, user_sid, &user_rid)) {
261 0 : return NT_STATUS_UNSUCCESSFUL;
262 : }
263 :
264 : /* Get user handle */
265 0 : status = dcerpc_samr_OpenUser(b,
266 : mem_ctx,
267 : samr_policy,
268 : SEC_FLAG_MAXIMUM_ALLOWED,
269 : user_rid,
270 : &user_policy,
271 : &result);
272 0 : if (!NT_STATUS_IS_OK(status)) {
273 0 : return status;
274 : }
275 0 : if (!NT_STATUS_IS_OK(result)) {
276 0 : return result;
277 : }
278 :
279 : /* Query user rids */
280 0 : status = dcerpc_samr_GetGroupsForUser(b,
281 : mem_ctx,
282 : &user_policy,
283 : &rid_array,
284 : &result);
285 : {
286 : NTSTATUS _result;
287 0 : dcerpc_samr_Close(b, mem_ctx, &user_policy, &_result);
288 : }
289 :
290 0 : if (!NT_STATUS_IS_OK(status)) {
291 0 : return status;
292 : }
293 0 : if (!NT_STATUS_IS_OK(result)) {
294 0 : return result;
295 : }
296 :
297 0 : num_groups = rid_array->count;
298 :
299 0 : user_grpsids = talloc_array(mem_ctx, struct dom_sid, num_groups);
300 0 : if (user_grpsids == NULL) {
301 0 : status = NT_STATUS_NO_MEMORY;
302 0 : return status;
303 : }
304 :
305 0 : for (i = 0; i < num_groups; i++) {
306 0 : sid_compose(&(user_grpsids[i]), domain_sid,
307 0 : rid_array->rids[i].rid);
308 : }
309 :
310 0 : *pnum_groups = num_groups;
311 :
312 0 : *puser_grpsids = user_grpsids;
313 :
314 0 : return NT_STATUS_OK;
315 : }
316 :
317 0 : NTSTATUS rpc_lookup_useraliases(TALLOC_CTX *mem_ctx,
318 : struct rpc_pipe_client *samr_pipe,
319 : struct policy_handle *samr_policy,
320 : uint32_t num_sids,
321 : const struct dom_sid *sids,
322 : uint32_t *pnum_aliases,
323 : uint32_t **palias_rids)
324 : {
325 : #define MAX_SAM_ENTRIES_W2K 0x400 /* 1024 */
326 0 : uint32_t num_query_sids = 0;
327 0 : uint32_t num_queries = 1;
328 0 : uint32_t num_aliases = 0;
329 0 : uint32_t total_sids = 0;
330 0 : uint32_t *alias_rids = NULL;
331 0 : uint32_t rangesize = MAX_SAM_ENTRIES_W2K;
332 : uint32_t i;
333 : struct samr_Ids alias_rids_query;
334 : NTSTATUS status, result;
335 0 : struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
336 :
337 : do {
338 : /* prepare query */
339 : struct lsa_SidArray sid_array;
340 :
341 0 : ZERO_STRUCT(sid_array);
342 :
343 0 : num_query_sids = MIN(num_sids - total_sids, rangesize);
344 :
345 0 : DEBUG(10,("rpc: lookup_useraliases: entering query %d for %d sids\n",
346 : num_queries, num_query_sids));
347 :
348 0 : if (num_query_sids) {
349 0 : sid_array.sids = talloc_zero_array(mem_ctx, struct lsa_SidPtr, num_query_sids);
350 0 : if (sid_array.sids == NULL) {
351 0 : return NT_STATUS_NO_MEMORY;
352 : }
353 : } else {
354 0 : sid_array.sids = NULL;
355 : }
356 :
357 0 : for (i = 0; i < num_query_sids; i++) {
358 0 : sid_array.sids[i].sid = dom_sid_dup(mem_ctx, &sids[total_sids++]);
359 0 : if (sid_array.sids[i].sid == NULL) {
360 0 : return NT_STATUS_NO_MEMORY;
361 : }
362 : }
363 0 : sid_array.num_sids = num_query_sids;
364 :
365 : /* do request */
366 0 : status = dcerpc_samr_GetAliasMembership(b,
367 : mem_ctx,
368 : samr_policy,
369 : &sid_array,
370 : &alias_rids_query,
371 : &result);
372 0 : if (!NT_STATUS_IS_OK(status)) {
373 0 : return status;
374 : }
375 0 : if (!NT_STATUS_IS_OK(result)) {
376 0 : return result;
377 : }
378 :
379 : /* process output */
380 0 : for (i = 0; i < alias_rids_query.count; i++) {
381 0 : size_t na = num_aliases;
382 :
383 0 : if (!add_rid_to_array_unique(mem_ctx,
384 0 : alias_rids_query.ids[i],
385 : &alias_rids,
386 : &na)) {
387 0 : return NT_STATUS_NO_MEMORY;
388 : }
389 0 : num_aliases = na;
390 : }
391 :
392 0 : num_queries++;
393 :
394 0 : } while (total_sids < num_sids);
395 :
396 0 : DEBUG(10,("rpc: rpc_lookup_useraliases: got %d aliases in %d queries "
397 : "(rangesize: %d)\n", num_aliases, num_queries, rangesize));
398 :
399 0 : *pnum_aliases = num_aliases;
400 0 : *palias_rids = alias_rids;
401 :
402 0 : return NT_STATUS_OK;
403 : #undef MAX_SAM_ENTRIES_W2K
404 : }
405 :
406 : /* Lookup group membership given a rid. */
407 0 : NTSTATUS rpc_lookup_groupmem(TALLOC_CTX *mem_ctx,
408 : struct rpc_pipe_client *samr_pipe,
409 : struct policy_handle *samr_policy,
410 : const char *domain_name,
411 : const struct dom_sid *domain_sid,
412 : const struct dom_sid *group_sid,
413 : enum lsa_SidType type,
414 : uint32_t *pnum_names,
415 : struct dom_sid **psid_mem,
416 : char ***pnames,
417 : uint32_t **pname_types)
418 : {
419 : struct policy_handle group_policy;
420 : uint32_t group_rid;
421 0 : uint32_t *rid_mem = NULL;
422 :
423 0 : uint32_t num_names = 0;
424 0 : uint32_t total_names = 0;
425 0 : struct dom_sid *sid_mem = NULL;
426 0 : char **names = NULL;
427 0 : uint32_t *name_types = NULL;
428 :
429 : struct lsa_Strings tmp_names;
430 : struct samr_Ids tmp_types;
431 :
432 : uint32_t j, r;
433 : NTSTATUS status, result;
434 0 : struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
435 :
436 0 : if (!sid_peek_check_rid(domain_sid, group_sid, &group_rid)) {
437 0 : return NT_STATUS_UNSUCCESSFUL;
438 : }
439 :
440 0 : switch(type) {
441 0 : case SID_NAME_DOM_GRP:
442 : {
443 0 : struct samr_RidAttrArray *rids = NULL;
444 :
445 0 : status = dcerpc_samr_OpenGroup(b,
446 : mem_ctx,
447 : samr_policy,
448 : SEC_FLAG_MAXIMUM_ALLOWED,
449 : group_rid,
450 : &group_policy,
451 : &result);
452 0 : if (!NT_STATUS_IS_OK(status)) {
453 0 : return status;
454 : }
455 0 : if (!NT_STATUS_IS_OK(result)) {
456 0 : return result;
457 : }
458 :
459 : /*
460 : * Step #1: Get a list of user rids that are the members of the group.
461 : */
462 0 : status = dcerpc_samr_QueryGroupMember(b,
463 : mem_ctx,
464 : &group_policy,
465 : &rids,
466 : &result);
467 : {
468 : NTSTATUS _result;
469 0 : dcerpc_samr_Close(b, mem_ctx, &group_policy, &_result);
470 : }
471 :
472 0 : if (!NT_STATUS_IS_OK(status)) {
473 0 : return status;
474 : }
475 0 : if (!NT_STATUS_IS_OK(result)) {
476 0 : return result;
477 : }
478 :
479 :
480 0 : if (rids == NULL || rids->count == 0) {
481 0 : pnum_names = 0;
482 0 : pnames = NULL;
483 0 : pname_types = NULL;
484 0 : psid_mem = NULL;
485 :
486 0 : return NT_STATUS_OK;
487 : }
488 :
489 0 : num_names = rids->count;
490 0 : rid_mem = rids->rids;
491 :
492 0 : break;
493 : }
494 0 : case SID_NAME_WKN_GRP:
495 : case SID_NAME_ALIAS:
496 : {
497 : struct lsa_SidArray sid_array;
498 : struct lsa_SidPtr sid_ptr;
499 : struct samr_Ids rids_query;
500 :
501 0 : sid_ptr.sid = dom_sid_dup(mem_ctx, group_sid);
502 0 : if (sid_ptr.sid == NULL) {
503 0 : return NT_STATUS_NO_MEMORY;
504 : }
505 :
506 0 : sid_array.num_sids = 1;
507 0 : sid_array.sids = &sid_ptr;
508 :
509 0 : status = dcerpc_samr_GetAliasMembership(b,
510 : mem_ctx,
511 : samr_policy,
512 : &sid_array,
513 : &rids_query,
514 : &result);
515 0 : if (!NT_STATUS_IS_OK(status)) {
516 0 : return status;
517 : }
518 0 : if (!NT_STATUS_IS_OK(result)) {
519 0 : return result;
520 : }
521 :
522 0 : if (rids_query.count == 0) {
523 0 : pnum_names = 0;
524 0 : pnames = NULL;
525 0 : pname_types = NULL;
526 0 : psid_mem = NULL;
527 :
528 0 : return NT_STATUS_OK;
529 : }
530 :
531 0 : num_names = rids_query.count;
532 0 : rid_mem = rids_query.ids;
533 :
534 0 : break;
535 : }
536 0 : default:
537 0 : return NT_STATUS_UNSUCCESSFUL;
538 : }
539 :
540 : /*
541 : * Step #2: Convert list of rids into list of usernames.
542 : */
543 0 : if (num_names > 0) {
544 0 : names = talloc_zero_array(mem_ctx, char *, num_names);
545 0 : name_types = talloc_zero_array(mem_ctx, uint32_t, num_names);
546 0 : sid_mem = talloc_zero_array(mem_ctx, struct dom_sid, num_names);
547 0 : if (names == NULL || name_types == NULL || sid_mem == NULL) {
548 0 : return NT_STATUS_NO_MEMORY;
549 : }
550 : }
551 :
552 0 : for (j = 0; j < num_names; j++) {
553 0 : sid_compose(&sid_mem[j], domain_sid, rid_mem[j]);
554 : }
555 :
556 0 : status = dcerpc_samr_LookupRids(b,
557 : mem_ctx,
558 : samr_policy,
559 : num_names,
560 : rid_mem,
561 : &tmp_names,
562 : &tmp_types,
563 : &result);
564 0 : if (!NT_STATUS_IS_OK(status)) {
565 0 : return status;
566 : }
567 :
568 0 : if (!NT_STATUS_IS_OK(result)) {
569 0 : if (!NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
570 0 : return result;
571 : }
572 : }
573 :
574 : /* Copy result into array. The talloc system will take
575 : care of freeing the temporary arrays later on. */
576 0 : if (tmp_names.count != num_names) {
577 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
578 : }
579 0 : if (tmp_types.count != num_names) {
580 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
581 : }
582 :
583 0 : for (r = 0; r < tmp_names.count; r++) {
584 0 : if (tmp_types.ids[r] == SID_NAME_UNKNOWN) {
585 0 : continue;
586 : }
587 0 : if (total_names >= num_names) {
588 0 : break;
589 : }
590 0 : names[total_names] = fill_domain_username_talloc(names,
591 : domain_name,
592 0 : tmp_names.names[r].string,
593 : true);
594 0 : if (names[total_names] == NULL) {
595 0 : return NT_STATUS_NO_MEMORY;
596 : }
597 0 : name_types[total_names] = tmp_types.ids[r];
598 0 : total_names++;
599 : }
600 :
601 0 : *pnum_names = total_names;
602 0 : *pnames = names;
603 0 : *pname_types = name_types;
604 0 : *psid_mem = sid_mem;
605 :
606 0 : return NT_STATUS_OK;
607 : }
608 :
609 : /* Get a list of trusted domains */
610 0 : NTSTATUS rpc_trusted_domains(TALLOC_CTX *mem_ctx,
611 : struct rpc_pipe_client *lsa_pipe,
612 : struct policy_handle *lsa_policy,
613 : uint32_t *pnum_trusts,
614 : struct netr_DomainTrust **ptrusts)
615 : {
616 0 : struct netr_DomainTrust *array = NULL;
617 0 : uint32_t enum_ctx = 0;
618 0 : uint32_t count = 0;
619 : NTSTATUS status, result;
620 0 : struct dcerpc_binding_handle *b = lsa_pipe->binding_handle;
621 :
622 : do {
623 : struct lsa_DomainList dom_list;
624 : struct lsa_DomainListEx dom_list_ex;
625 0 : bool has_ex = false;
626 : uint32_t i;
627 :
628 : /*
629 : * We don't run into deadlocks here, cause winbind_off() is
630 : * called in the main function.
631 : */
632 0 : status = dcerpc_lsa_EnumTrustedDomainsEx(b,
633 : mem_ctx,
634 : lsa_policy,
635 : &enum_ctx,
636 : &dom_list_ex,
637 : (uint32_t) -1,
638 : &result);
639 0 : if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_ERR(result) &&
640 0 : dom_list_ex.count > 0) {
641 0 : count += dom_list_ex.count;
642 0 : has_ex = true;
643 : } else {
644 0 : status = dcerpc_lsa_EnumTrustDom(b,
645 : mem_ctx,
646 : lsa_policy,
647 : &enum_ctx,
648 : &dom_list,
649 : (uint32_t) -1,
650 : &result);
651 0 : if (!NT_STATUS_IS_OK(status)) {
652 0 : return status;
653 : }
654 0 : if (!NT_STATUS_IS_OK(result)) {
655 0 : if (!NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
656 0 : return result;
657 : }
658 : }
659 :
660 0 : count += dom_list.count;
661 : }
662 :
663 0 : array = talloc_realloc(mem_ctx,
664 : array,
665 : struct netr_DomainTrust,
666 : count);
667 0 : if (array == NULL) {
668 0 : return NT_STATUS_NO_MEMORY;
669 : }
670 :
671 0 : for (i = 0; i < count; i++) {
672 0 : struct netr_DomainTrust *trust = &array[i];
673 : struct dom_sid *sid;
674 :
675 0 : ZERO_STRUCTP(trust);
676 :
677 0 : sid = talloc(array, struct dom_sid);
678 0 : if (sid == NULL) {
679 0 : return NT_STATUS_NO_MEMORY;
680 : }
681 :
682 0 : if (dom_list_ex.domains[i].sid == NULL) {
683 0 : DBG_ERR("Trusted domain %s has no SID, "
684 : "skipping!\n",
685 : trust->dns_name);
686 0 : continue;
687 : }
688 :
689 0 : if (has_ex) {
690 0 : trust->netbios_name = talloc_move(array,
691 : &dom_list_ex.domains[i].netbios_name.string);
692 0 : trust->dns_name = talloc_move(array,
693 : &dom_list_ex.domains[i].domain_name.string);
694 0 : sid_copy(sid, dom_list_ex.domains[i].sid);
695 : } else {
696 0 : trust->netbios_name = talloc_move(array,
697 : &dom_list.domains[i].name.string);
698 0 : trust->dns_name = NULL;
699 :
700 0 : sid_copy(sid, dom_list.domains[i].sid);
701 : }
702 :
703 0 : trust->sid = sid;
704 : }
705 0 : } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
706 :
707 0 : *pnum_trusts = count;
708 0 : *ptrusts = array;
709 :
710 0 : return NT_STATUS_OK;
711 : }
712 :
713 0 : static NTSTATUS rpc_try_lookup_sids3(TALLOC_CTX *mem_ctx,
714 : struct winbindd_domain *domain,
715 : struct rpc_pipe_client *cli,
716 : struct lsa_SidArray *sids,
717 : struct lsa_RefDomainList **pdomains,
718 : struct lsa_TransNameArray **pnames)
719 : {
720 : struct lsa_TransNameArray2 lsa_names2;
721 0 : struct lsa_TransNameArray *names = *pnames;
722 0 : uint32_t i, count = 0;
723 : NTSTATUS status, result;
724 :
725 0 : ZERO_STRUCT(lsa_names2);
726 0 : status = dcerpc_lsa_LookupSids3(cli->binding_handle,
727 : mem_ctx,
728 : sids,
729 : pdomains,
730 : &lsa_names2,
731 : LSA_LOOKUP_NAMES_ALL,
732 : &count,
733 : LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES,
734 : LSA_CLIENT_REVISION_2,
735 : &result);
736 0 : if (!NT_STATUS_IS_OK(status)) {
737 0 : return status;
738 : }
739 0 : if (NT_STATUS_LOOKUP_ERR(result)) {
740 0 : return result;
741 : }
742 0 : if (sids->num_sids != lsa_names2.count) {
743 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
744 : }
745 :
746 0 : names->count = lsa_names2.count;
747 0 : names->names = talloc_array(names, struct lsa_TranslatedName,
748 : names->count);
749 0 : if (names->names == NULL) {
750 0 : return NT_STATUS_NO_MEMORY;
751 : }
752 0 : for (i=0; i<names->count; i++) {
753 0 : names->names[i].sid_type = lsa_names2.names[i].sid_type;
754 0 : names->names[i].name.string = talloc_move(
755 : names->names, &lsa_names2.names[i].name.string);
756 0 : names->names[i].sid_index = lsa_names2.names[i].sid_index;
757 :
758 0 : if (names->names[i].sid_index == UINT32_MAX) {
759 0 : continue;
760 : }
761 0 : if ((*pdomains) == NULL) {
762 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
763 : }
764 0 : if (names->names[i].sid_index >= (*pdomains)->count) {
765 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
766 : }
767 : }
768 0 : return NT_STATUS_OK;
769 : }
770 :
771 0 : NTSTATUS rpc_lookup_sids(TALLOC_CTX *mem_ctx,
772 : struct winbindd_domain *domain,
773 : struct lsa_SidArray *sids,
774 : struct lsa_RefDomainList **pdomains,
775 : struct lsa_TransNameArray **pnames)
776 : {
777 0 : struct lsa_TransNameArray *names = *pnames;
778 0 : struct rpc_pipe_client *cli = NULL;
779 : struct policy_handle lsa_policy;
780 : uint32_t count;
781 : uint32_t i;
782 : NTSTATUS status, result;
783 :
784 0 : status = cm_connect_lsat(domain, mem_ctx, &cli, &lsa_policy);
785 0 : if (!NT_STATUS_IS_OK(status)) {
786 0 : return status;
787 : }
788 :
789 0 : if (cli->transport->transport == NCACN_IP_TCP) {
790 0 : return rpc_try_lookup_sids3(mem_ctx, domain, cli, sids,
791 : pdomains, pnames);
792 : }
793 :
794 0 : status = dcerpc_lsa_LookupSids(cli->binding_handle, mem_ctx,
795 : &lsa_policy, sids, pdomains,
796 : names, LSA_LOOKUP_NAMES_ALL,
797 : &count, &result);
798 0 : if (!NT_STATUS_IS_OK(status)) {
799 0 : return status;
800 : }
801 0 : if (NT_STATUS_LOOKUP_ERR(result)) {
802 0 : return result;
803 : }
804 :
805 0 : if (sids->num_sids != names->count) {
806 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
807 : }
808 :
809 0 : for (i=0; i < names->count; i++) {
810 0 : if (names->names[i].sid_index == UINT32_MAX) {
811 0 : continue;
812 : }
813 0 : if ((*pdomains) == NULL) {
814 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
815 : }
816 0 : if (names->names[i].sid_index >= (*pdomains)->count) {
817 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
818 : }
819 : }
820 :
821 0 : return NT_STATUS_OK;
822 : }
|