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 0 : 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 0 : do {
61 0 : struct samr_SamArray *sam_array = NULL;
62 0 : uint32_t count = 0;
63 0 : 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 0 : NTSTATUS status, result;
118 0 : struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
119 :
120 0 : *pnum_info = 0;
121 :
122 0 : do {
123 0 : struct samr_SamArray *sam_array = NULL;
124 0 : uint32_t count = 0;
125 0 : 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 0 : NTSTATUS status, result;
186 0 : struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
187 :
188 0 : *pnum_info = 0;
189 :
190 0 : do {
191 0 : struct samr_SamArray *sam_array = NULL;
192 0 : uint32_t count = 0;
193 0 : uint32_t start = num_info;
194 0 : 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 0 : 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 0 : uint32_t user_rid;
257 0 : 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 0 : 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_queries = 1;
327 0 : uint32_t num_aliases = 0;
328 0 : uint32_t total_sids = 0;
329 0 : uint32_t *alias_rids = NULL;
330 0 : uint32_t rangesize = MAX_SAM_ENTRIES_W2K;
331 0 : uint32_t i;
332 0 : struct samr_Ids alias_rids_query;
333 0 : NTSTATUS status, result;
334 0 : struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
335 :
336 0 : do {
337 : /* prepare query */
338 0 : struct lsa_SidArray sid_array;
339 0 : uint32_t num_query_sids = 0;
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 0 : struct policy_handle group_policy;
420 0 : 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 0 : struct lsa_Strings tmp_names;
430 0 : struct samr_Ids tmp_types;
431 :
432 0 : uint32_t j, r;
433 0 : 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 0 : 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 : default:
495 0 : return NT_STATUS_UNSUCCESSFUL;
496 : }
497 :
498 : /*
499 : * Step #2: Convert list of rids into list of usernames.
500 : */
501 0 : if (num_names > 0) {
502 0 : names = talloc_zero_array(mem_ctx, char *, num_names);
503 0 : name_types = talloc_zero_array(mem_ctx, uint32_t, num_names);
504 0 : sid_mem = talloc_zero_array(mem_ctx, struct dom_sid, num_names);
505 0 : if (names == NULL || name_types == NULL || sid_mem == NULL) {
506 0 : return NT_STATUS_NO_MEMORY;
507 : }
508 : }
509 :
510 0 : for (j = 0; j < num_names; j++) {
511 0 : sid_compose(&sid_mem[j], domain_sid, rid_mem[j]);
512 : }
513 :
514 0 : status = dcerpc_samr_LookupRids(b,
515 : mem_ctx,
516 : samr_policy,
517 : num_names,
518 : rid_mem,
519 : &tmp_names,
520 : &tmp_types,
521 : &result);
522 0 : if (!NT_STATUS_IS_OK(status)) {
523 0 : return status;
524 : }
525 :
526 0 : if (!NT_STATUS_IS_OK(result)) {
527 0 : if (!NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
528 0 : return result;
529 : }
530 : }
531 :
532 : /* Copy result into array. The talloc system will take
533 : care of freeing the temporary arrays later on. */
534 0 : if (tmp_names.count != num_names) {
535 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
536 : }
537 0 : if (tmp_types.count != num_names) {
538 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
539 : }
540 :
541 0 : for (r = 0; r < tmp_names.count; r++) {
542 0 : if (tmp_types.ids[r] == SID_NAME_UNKNOWN) {
543 0 : continue;
544 : }
545 0 : if (total_names >= num_names) {
546 0 : break;
547 : }
548 0 : names[total_names] = fill_domain_username_talloc(names,
549 : domain_name,
550 0 : tmp_names.names[r].string,
551 : true);
552 0 : if (names[total_names] == NULL) {
553 0 : return NT_STATUS_NO_MEMORY;
554 : }
555 0 : name_types[total_names] = tmp_types.ids[r];
556 0 : total_names++;
557 : }
558 :
559 0 : *pnum_names = total_names;
560 0 : *pnames = names;
561 0 : *pname_types = name_types;
562 0 : *psid_mem = sid_mem;
563 :
564 0 : return NT_STATUS_OK;
565 : }
566 :
567 : /* Lookup alias membership using a rid taken from alias_sid. */
568 0 : NTSTATUS rpc_lookup_aliasmem(TALLOC_CTX *mem_ctx,
569 : struct rpc_pipe_client *samr_pipe,
570 : struct policy_handle *samr_policy,
571 : const struct dom_sid *domain_sid,
572 : const struct dom_sid *alias_sid,
573 : enum lsa_SidType type,
574 : uint32_t *pnum_sids,
575 : struct dom_sid **psids)
576 : {
577 0 : uint32_t alias_rid;
578 0 : struct dom_sid *sid_mem = NULL;
579 0 : struct lsa_SidArray sid_array;
580 0 : uint32_t i;
581 0 : NTSTATUS status, result;
582 0 : struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
583 :
584 0 : if (!sid_peek_check_rid(domain_sid, alias_sid, &alias_rid)) {
585 0 : return NT_STATUS_UNSUCCESSFUL;
586 : }
587 :
588 0 : switch (type) {
589 0 : case SID_NAME_ALIAS: {
590 0 : struct policy_handle alias_policy;
591 :
592 0 : status = dcerpc_samr_OpenAlias(b,
593 : mem_ctx,
594 : samr_policy,
595 : SEC_FLAG_MAXIMUM_ALLOWED,
596 : alias_rid,
597 : &alias_policy,
598 : &result);
599 0 : if (any_nt_status_not_ok(status, result, &status)) {
600 0 : return status;
601 : }
602 :
603 0 : status = dcerpc_samr_GetMembersInAlias(b,
604 : mem_ctx,
605 : &alias_policy,
606 : &sid_array,
607 : &result);
608 : {
609 0 : NTSTATUS _result;
610 0 : dcerpc_samr_Close(b, mem_ctx, &alias_policy, &_result);
611 : }
612 0 : if (any_nt_status_not_ok(status, result, &status)) {
613 0 : return status;
614 : }
615 :
616 0 : sid_mem = talloc_zero_array(mem_ctx,
617 : struct dom_sid,
618 : sid_array.num_sids);
619 0 : if (sid_mem == NULL) {
620 0 : return NT_STATUS_NO_MEMORY;
621 : }
622 :
623 : /*
624 : * We cannot just simply assign '*psids = sid_array.sids;'
625 : * we need to copy every sid since these are incompatible types:
626 : * 'struct dom_sid *' vs 'struct lsa_SidPtr *'
627 : */
628 0 : for (i = 0; i < sid_array.num_sids; i++) {
629 0 : sid_copy(&sid_mem[i], sid_array.sids[i].sid);
630 : }
631 :
632 0 : *pnum_sids = sid_array.num_sids;
633 0 : *psids = sid_mem;
634 :
635 0 : return NT_STATUS_OK;
636 : }
637 0 : default:
638 0 : return NT_STATUS_UNSUCCESSFUL;
639 : }
640 : }
641 :
642 : /* Get a list of trusted domains */
643 0 : NTSTATUS rpc_trusted_domains(TALLOC_CTX *mem_ctx,
644 : struct rpc_pipe_client *lsa_pipe,
645 : struct policy_handle *lsa_policy,
646 : uint32_t *pnum_trusts,
647 : struct netr_DomainTrust **ptrusts)
648 : {
649 0 : struct netr_DomainTrust *array = NULL;
650 0 : uint32_t enum_ctx = 0;
651 0 : uint32_t count = 0;
652 0 : NTSTATUS status, result;
653 0 : struct dcerpc_binding_handle *b = lsa_pipe->binding_handle;
654 :
655 0 : do {
656 0 : struct lsa_DomainList dom_list;
657 0 : struct lsa_DomainListEx dom_list_ex;
658 0 : bool has_ex = false;
659 0 : uint32_t i;
660 :
661 : /*
662 : * We don't run into deadlocks here, cause winbind_off() is
663 : * called in the main function.
664 : */
665 0 : status = dcerpc_lsa_EnumTrustedDomainsEx(b,
666 : mem_ctx,
667 : lsa_policy,
668 : &enum_ctx,
669 : &dom_list_ex,
670 : (uint32_t) -1,
671 : &result);
672 0 : if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_ERR(result) &&
673 0 : dom_list_ex.count > 0) {
674 0 : count += dom_list_ex.count;
675 0 : has_ex = true;
676 : } else {
677 0 : status = dcerpc_lsa_EnumTrustDom(b,
678 : mem_ctx,
679 : lsa_policy,
680 : &enum_ctx,
681 : &dom_list,
682 : (uint32_t) -1,
683 : &result);
684 0 : if (!NT_STATUS_IS_OK(status)) {
685 0 : return status;
686 : }
687 0 : if (!NT_STATUS_IS_OK(result)) {
688 0 : if (!NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
689 0 : return result;
690 : }
691 : }
692 :
693 0 : count += dom_list.count;
694 : }
695 :
696 0 : array = talloc_realloc(mem_ctx,
697 : array,
698 : struct netr_DomainTrust,
699 : count);
700 0 : if (array == NULL) {
701 0 : return NT_STATUS_NO_MEMORY;
702 : }
703 :
704 0 : for (i = 0; i < count; i++) {
705 0 : struct netr_DomainTrust *trust = &array[i];
706 0 : struct dom_sid *sid;
707 :
708 0 : ZERO_STRUCTP(trust);
709 :
710 0 : sid = talloc(array, struct dom_sid);
711 0 : if (sid == NULL) {
712 0 : return NT_STATUS_NO_MEMORY;
713 : }
714 :
715 0 : if (dom_list_ex.domains[i].sid == NULL) {
716 0 : DBG_ERR("Trusted domain %s has no SID, "
717 : "skipping!\n",
718 : trust->dns_name);
719 0 : continue;
720 : }
721 :
722 0 : if (has_ex) {
723 0 : trust->netbios_name = talloc_move(array,
724 : &dom_list_ex.domains[i].netbios_name.string);
725 0 : trust->dns_name = talloc_move(array,
726 : &dom_list_ex.domains[i].domain_name.string);
727 0 : sid_copy(sid, dom_list_ex.domains[i].sid);
728 : } else {
729 0 : trust->netbios_name = talloc_move(array,
730 : &dom_list.domains[i].name.string);
731 0 : trust->dns_name = NULL;
732 :
733 0 : sid_copy(sid, dom_list.domains[i].sid);
734 : }
735 :
736 0 : trust->sid = sid;
737 : }
738 0 : } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
739 :
740 0 : *pnum_trusts = count;
741 0 : *ptrusts = array;
742 :
743 0 : return NT_STATUS_OK;
744 : }
745 :
746 0 : static NTSTATUS rpc_try_lookup_sids3(TALLOC_CTX *mem_ctx,
747 : struct winbindd_domain *domain,
748 : struct rpc_pipe_client *cli,
749 : struct lsa_SidArray *sids,
750 : struct lsa_RefDomainList **pdomains,
751 : struct lsa_TransNameArray **pnames)
752 : {
753 0 : struct lsa_TransNameArray2 lsa_names2;
754 0 : struct lsa_TransNameArray *names = *pnames;
755 0 : uint32_t i, count = 0;
756 0 : NTSTATUS status, result;
757 :
758 0 : ZERO_STRUCT(lsa_names2);
759 0 : status = dcerpc_lsa_LookupSids3(cli->binding_handle,
760 : mem_ctx,
761 : sids,
762 : pdomains,
763 : &lsa_names2,
764 : LSA_LOOKUP_NAMES_ALL,
765 : &count,
766 : LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES,
767 : LSA_CLIENT_REVISION_2,
768 : &result);
769 0 : if (!NT_STATUS_IS_OK(status)) {
770 0 : return status;
771 : }
772 0 : if (NT_STATUS_LOOKUP_ERR(result)) {
773 0 : return result;
774 : }
775 0 : if (sids->num_sids != lsa_names2.count) {
776 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
777 : }
778 :
779 0 : names->count = lsa_names2.count;
780 0 : names->names = talloc_array(names, struct lsa_TranslatedName,
781 : names->count);
782 0 : if (names->names == NULL) {
783 0 : return NT_STATUS_NO_MEMORY;
784 : }
785 0 : for (i=0; i<names->count; i++) {
786 0 : names->names[i].sid_type = lsa_names2.names[i].sid_type;
787 0 : names->names[i].name.string = talloc_move(
788 : names->names, &lsa_names2.names[i].name.string);
789 0 : names->names[i].sid_index = lsa_names2.names[i].sid_index;
790 :
791 0 : if (names->names[i].sid_index == UINT32_MAX) {
792 0 : continue;
793 : }
794 0 : if ((*pdomains) == NULL) {
795 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
796 : }
797 0 : if (names->names[i].sid_index >= (*pdomains)->count) {
798 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
799 : }
800 : }
801 0 : return NT_STATUS_OK;
802 : }
803 :
804 0 : NTSTATUS rpc_lookup_sids(TALLOC_CTX *mem_ctx,
805 : struct winbindd_domain *domain,
806 : struct lsa_SidArray *sids,
807 : struct lsa_RefDomainList **pdomains,
808 : struct lsa_TransNameArray **pnames)
809 : {
810 0 : struct lsa_TransNameArray *names = *pnames;
811 0 : struct rpc_pipe_client *cli = NULL;
812 0 : struct policy_handle lsa_policy;
813 0 : uint32_t count;
814 0 : uint32_t i;
815 0 : NTSTATUS status, result;
816 :
817 0 : status = cm_connect_lsat(domain, mem_ctx, &cli, &lsa_policy);
818 0 : if (!NT_STATUS_IS_OK(status)) {
819 0 : return status;
820 : }
821 :
822 0 : if (cli->transport->transport == NCACN_IP_TCP) {
823 0 : return rpc_try_lookup_sids3(mem_ctx, domain, cli, sids,
824 : pdomains, pnames);
825 : }
826 :
827 0 : status = dcerpc_lsa_LookupSids(cli->binding_handle, mem_ctx,
828 : &lsa_policy, sids, pdomains,
829 : names, LSA_LOOKUP_NAMES_ALL,
830 : &count, &result);
831 0 : if (!NT_STATUS_IS_OK(status)) {
832 0 : return status;
833 : }
834 0 : if (NT_STATUS_LOOKUP_ERR(result)) {
835 0 : return result;
836 : }
837 :
838 0 : if (sids->num_sids != names->count) {
839 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
840 : }
841 :
842 0 : for (i=0; i < names->count; i++) {
843 0 : if (names->names[i].sid_index == UINT32_MAX) {
844 0 : continue;
845 : }
846 0 : if ((*pdomains) == NULL) {
847 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
848 : }
849 0 : if (names->names[i].sid_index >= (*pdomains)->count) {
850 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
851 : }
852 : }
853 :
854 0 : return NT_STATUS_OK;
855 : }
|