dbwrap: add parse_record_send/recv to struct db_context
[Samba.git] / source3 / winbindd / winbindd_rpc.c
blob0023e2aa8d764ad3a27eb6644203b97061f4e708
1 /*
2 * Unix SMB/CIFS implementation.
4 * Winbind rpc backend functions
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>
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.
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.
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/>.
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"
37 /* Query display info for a domain */
38 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)
44 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
45 uint32_t *rids = NULL;
46 uint32_t num_rids = 0;
47 uint32_t i = 0;
48 uint32_t resume_handle = 0;
49 NTSTATUS result;
51 *prids = NULL;
53 do {
54 struct samr_SamArray *sam_array = NULL;
55 uint32_t count = 0;
56 NTSTATUS status;
57 uint32_t *tmp;
59 status = dcerpc_samr_EnumDomainUsers(
60 b, mem_ctx, samr_policy, &resume_handle,
61 ACB_NORMAL, &sam_array, 0xffff, &count, &result);
62 if (!NT_STATUS_IS_OK(status)) {
63 return status;
65 if (!NT_STATUS_IS_OK(result)) {
66 if (!NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
67 DBG_WARNING("EnumDomainUsers failed: %s\n",
68 nt_errstr(result));
69 TALLOC_FREE(rids);
70 TALLOC_FREE(sam_array);
71 return result;
75 if (num_rids + count < num_rids) {
76 TALLOC_FREE(sam_array);
77 TALLOC_FREE(rids);
78 return NT_STATUS_INTEGER_OVERFLOW;
81 tmp = talloc_realloc(mem_ctx, rids, uint32_t, num_rids+count);
82 if (tmp == NULL) {
83 TALLOC_FREE(sam_array);
84 TALLOC_FREE(rids);
85 return NT_STATUS_NO_MEMORY;
87 rids = tmp;
89 for (i=0; i<count; i++) {
90 rids[num_rids++] = sam_array->entries[i].idx;
92 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
94 *prids = rids;
96 return NT_STATUS_OK;
99 /* List all domain groups */
100 NTSTATUS rpc_enum_dom_groups(TALLOC_CTX *mem_ctx,
101 struct rpc_pipe_client *samr_pipe,
102 struct policy_handle *samr_policy,
103 uint32_t *pnum_info,
104 struct wb_acct_info **pinfo)
106 struct wb_acct_info *info = NULL;
107 uint32_t start = 0;
108 uint32_t num_info = 0;
109 NTSTATUS status, result;
110 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
112 *pnum_info = 0;
114 do {
115 struct samr_SamArray *sam_array = NULL;
116 uint32_t count = 0;
117 uint32_t g;
119 /* start is updated by this call. */
120 status = dcerpc_samr_EnumDomainGroups(b,
121 mem_ctx,
122 samr_policy,
123 &start,
124 &sam_array,
125 0xFFFF, /* buffer size? */
126 &count,
127 &result);
128 if (!NT_STATUS_IS_OK(status)) {
129 return status;
131 if (!NT_STATUS_IS_OK(result)) {
132 if (!NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
133 DEBUG(2,("query_user_list: failed to enum domain groups: %s\n",
134 nt_errstr(result)));
135 return result;
139 info = talloc_realloc(mem_ctx,
140 info,
141 struct wb_acct_info,
142 num_info + count);
143 if (info == NULL) {
144 return NT_STATUS_NO_MEMORY;
147 for (g = 0; g < count; g++) {
148 struct wb_acct_info *i = &info[num_info + g];
150 fstrcpy(i->acct_name,
151 sam_array->entries[g].name.string);
152 fstrcpy(i->acct_desc, "");
153 i->rid = sam_array->entries[g].idx;
156 num_info += count;
157 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
159 *pnum_info = num_info;
160 *pinfo = info;
162 return NT_STATUS_OK;
165 NTSTATUS rpc_enum_local_groups(TALLOC_CTX *mem_ctx,
166 struct rpc_pipe_client *samr_pipe,
167 struct policy_handle *samr_policy,
168 uint32_t *pnum_info,
169 struct wb_acct_info **pinfo)
171 struct wb_acct_info *info = NULL;
172 uint32_t num_info = 0;
173 NTSTATUS status, result;
174 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
176 *pnum_info = 0;
178 do {
179 struct samr_SamArray *sam_array = NULL;
180 uint32_t count = 0;
181 uint32_t start = num_info;
182 uint32_t g;
184 status = dcerpc_samr_EnumDomainAliases(b,
185 mem_ctx,
186 samr_policy,
187 &start,
188 &sam_array,
189 0xFFFF, /* buffer size? */
190 &count,
191 &result);
192 if (!NT_STATUS_IS_OK(status)) {
193 return status;
195 if (!NT_STATUS_IS_OK(result)) {
196 if (!NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
197 return result;
201 info = talloc_realloc(mem_ctx,
202 info,
203 struct wb_acct_info,
204 num_info + count);
205 if (info == NULL) {
206 return NT_STATUS_NO_MEMORY;
209 for (g = 0; g < count; g++) {
210 struct wb_acct_info *i = &info[num_info + g];
212 fstrcpy(i->acct_name,
213 sam_array->entries[g].name.string);
214 fstrcpy(i->acct_desc, "");
215 i->rid = sam_array->entries[g].idx;
218 num_info += count;
219 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
221 *pnum_info = num_info;
222 *pinfo = info;
224 return NT_STATUS_OK;
227 /* convert a single name to a sid in a domain */
228 NTSTATUS rpc_name_to_sid(TALLOC_CTX *mem_ctx,
229 struct rpc_pipe_client *lsa_pipe,
230 struct policy_handle *lsa_policy,
231 const char *domain_name,
232 const char *name,
233 uint32_t flags,
234 struct dom_sid *sid,
235 enum lsa_SidType *type)
237 enum lsa_SidType *types = NULL;
238 struct dom_sid *sids = NULL;
239 char *full_name = NULL;
240 const char *names[1];
241 char *mapped_name = NULL;
242 NTSTATUS status;
244 if (name == NULL || name[0] == '\0') {
245 full_name = talloc_asprintf(mem_ctx, "%s", domain_name);
246 } else if (domain_name == NULL || domain_name[0] == '\0') {
247 full_name = talloc_asprintf(mem_ctx, "%s", name);
248 } else {
249 full_name = talloc_asprintf(mem_ctx, "%s\\%s", domain_name, name);
252 if (full_name == NULL) {
253 return NT_STATUS_NO_MEMORY;
256 status = normalize_name_unmap(mem_ctx, full_name, &mapped_name);
257 /* Reset the full_name pointer if we mapped anything */
258 if (NT_STATUS_IS_OK(status) ||
259 NT_STATUS_EQUAL(status, NT_STATUS_FILE_RENAMED)) {
260 full_name = mapped_name;
263 DEBUG(3,("name_to_sid: %s for domain %s\n",
264 full_name ? full_name : "", domain_name ));
266 names[0] = full_name;
269 * We don't run into deadlocks here, cause winbind_off() is
270 * called in the main function.
272 status = rpccli_lsa_lookup_names(lsa_pipe,
273 mem_ctx,
274 lsa_policy,
275 1, /* num_names */
276 names,
277 NULL, /* domains */
278 1, /* level */
279 &sids,
280 &types);
281 if (!NT_STATUS_IS_OK(status)) {
282 DEBUG(2,("name_to_sid: failed to lookup name: %s\n",
283 nt_errstr(status)));
284 return status;
287 sid_copy(sid, &sids[0]);
288 *type = types[0];
290 return NT_STATUS_OK;
293 /* Convert a domain SID to a user or group name */
294 NTSTATUS rpc_sid_to_name(TALLOC_CTX *mem_ctx,
295 struct rpc_pipe_client *lsa_pipe,
296 struct policy_handle *lsa_policy,
297 struct winbindd_domain *domain,
298 const struct dom_sid *sid,
299 char **pdomain_name,
300 char **pname,
301 enum lsa_SidType *ptype)
303 char *mapped_name = NULL;
304 char **domains = NULL;
305 char **names = NULL;
306 enum lsa_SidType *types = NULL;
307 NTSTATUS map_status;
308 NTSTATUS status;
310 status = rpccli_lsa_lookup_sids(lsa_pipe,
311 mem_ctx,
312 lsa_policy,
313 1, /* num_sids */
314 sid,
315 &domains,
316 &names,
317 &types);
318 if (!NT_STATUS_IS_OK(status)) {
319 DEBUG(2,("sid_to_name: failed to lookup sids: %s\n",
320 nt_errstr(status)));
321 return status;
324 *ptype = (enum lsa_SidType) types[0];
326 map_status = normalize_name_map(mem_ctx,
327 domain,
328 names[0],
329 &mapped_name);
330 if (NT_STATUS_IS_OK(map_status) ||
331 NT_STATUS_EQUAL(map_status, NT_STATUS_FILE_RENAMED)) {
332 *pname = talloc_strdup(mem_ctx, mapped_name);
333 DEBUG(5,("returning mapped name -- %s\n", *pname));
334 } else {
335 *pname = talloc_strdup(mem_ctx, names[0]);
337 if ((names[0] != NULL) && (*pname == NULL)) {
338 return NT_STATUS_NO_MEMORY;
341 *pdomain_name = talloc_strdup(mem_ctx, domains[0]);
342 if (*pdomain_name == NULL) {
343 return NT_STATUS_NO_MEMORY;
346 return NT_STATUS_OK;
349 /* Convert a bunch of rids to user or group names */
350 NTSTATUS rpc_rids_to_names(TALLOC_CTX *mem_ctx,
351 struct rpc_pipe_client *lsa_pipe,
352 struct policy_handle *lsa_policy,
353 struct winbindd_domain *domain,
354 const struct dom_sid *sid,
355 uint32_t *rids,
356 size_t num_rids,
357 char **pdomain_name,
358 char ***pnames,
359 enum lsa_SidType **ptypes)
361 enum lsa_SidType *types = NULL;
362 char *domain_name = NULL;
363 char **domains = NULL;
364 char **names = NULL;
365 struct dom_sid *sids;
366 size_t i;
367 NTSTATUS status;
369 if (num_rids > 0) {
370 sids = talloc_array(mem_ctx, struct dom_sid, num_rids);
371 if (sids == NULL) {
372 return NT_STATUS_NO_MEMORY;
374 } else {
375 sids = NULL;
378 for (i = 0; i < num_rids; i++) {
379 if (!sid_compose(&sids[i], sid, rids[i])) {
380 return NT_STATUS_INTERNAL_ERROR;
384 status = rpccli_lsa_lookup_sids(lsa_pipe,
385 mem_ctx,
386 lsa_policy,
387 num_rids,
388 sids,
389 &domains,
390 &names,
391 &types);
392 if (!NT_STATUS_IS_OK(status) &&
393 !NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
394 DEBUG(2,("rids_to_names: failed to lookup sids: %s\n",
395 nt_errstr(status)));
396 return status;
399 for (i = 0; i < num_rids; i++) {
400 char *mapped_name = NULL;
401 NTSTATUS map_status;
403 if (types[i] != SID_NAME_UNKNOWN) {
404 map_status = normalize_name_map(mem_ctx,
405 domain,
406 names[i],
407 &mapped_name);
408 if (NT_STATUS_IS_OK(map_status) ||
409 NT_STATUS_EQUAL(map_status, NT_STATUS_FILE_RENAMED)) {
410 TALLOC_FREE(names[i]);
411 names[i] = talloc_strdup(names, mapped_name);
412 if (names[i] == NULL) {
413 return NT_STATUS_NO_MEMORY;
417 domain_name = domains[i];
421 *pdomain_name = domain_name;
422 *ptypes = types;
423 *pnames = names;
425 return NT_STATUS_OK;
428 /* Lookup groups a user is a member of. */
429 NTSTATUS rpc_lookup_usergroups(TALLOC_CTX *mem_ctx,
430 struct rpc_pipe_client *samr_pipe,
431 struct policy_handle *samr_policy,
432 const struct dom_sid *domain_sid,
433 const struct dom_sid *user_sid,
434 uint32_t *pnum_groups,
435 struct dom_sid **puser_grpsids)
437 struct policy_handle user_policy;
438 struct samr_RidWithAttributeArray *rid_array = NULL;
439 struct dom_sid *user_grpsids = NULL;
440 uint32_t num_groups = 0, i;
441 uint32_t user_rid;
442 NTSTATUS status, result;
443 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
445 if (!sid_peek_check_rid(domain_sid, user_sid, &user_rid)) {
446 return NT_STATUS_UNSUCCESSFUL;
449 /* Get user handle */
450 status = dcerpc_samr_OpenUser(b,
451 mem_ctx,
452 samr_policy,
453 SEC_FLAG_MAXIMUM_ALLOWED,
454 user_rid,
455 &user_policy,
456 &result);
457 if (!NT_STATUS_IS_OK(status)) {
458 return status;
460 if (!NT_STATUS_IS_OK(result)) {
461 return result;
464 /* Query user rids */
465 status = dcerpc_samr_GetGroupsForUser(b,
466 mem_ctx,
467 &user_policy,
468 &rid_array,
469 &result);
471 NTSTATUS _result;
472 dcerpc_samr_Close(b, mem_ctx, &user_policy, &_result);
475 if (!NT_STATUS_IS_OK(status)) {
476 return status;
478 if (!NT_STATUS_IS_OK(result)) {
479 return result;
482 num_groups = rid_array->count;
484 user_grpsids = talloc_array(mem_ctx, struct dom_sid, num_groups);
485 if (user_grpsids == NULL) {
486 status = NT_STATUS_NO_MEMORY;
487 return status;
490 for (i = 0; i < num_groups; i++) {
491 sid_compose(&(user_grpsids[i]), domain_sid,
492 rid_array->rids[i].rid);
495 *pnum_groups = num_groups;
497 *puser_grpsids = user_grpsids;
499 return NT_STATUS_OK;
502 NTSTATUS rpc_lookup_useraliases(TALLOC_CTX *mem_ctx,
503 struct rpc_pipe_client *samr_pipe,
504 struct policy_handle *samr_policy,
505 uint32_t num_sids,
506 const struct dom_sid *sids,
507 uint32_t *pnum_aliases,
508 uint32_t **palias_rids)
510 #define MAX_SAM_ENTRIES_W2K 0x400 /* 1024 */
511 uint32_t num_query_sids = 0;
512 uint32_t num_queries = 1;
513 uint32_t num_aliases = 0;
514 uint32_t total_sids = 0;
515 uint32_t *alias_rids = NULL;
516 uint32_t rangesize = MAX_SAM_ENTRIES_W2K;
517 uint32_t i;
518 struct samr_Ids alias_rids_query;
519 NTSTATUS status, result;
520 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
522 do {
523 /* prepare query */
524 struct lsa_SidArray sid_array;
526 ZERO_STRUCT(sid_array);
528 num_query_sids = MIN(num_sids - total_sids, rangesize);
530 DEBUG(10,("rpc: lookup_useraliases: entering query %d for %d sids\n",
531 num_queries, num_query_sids));
533 if (num_query_sids) {
534 sid_array.sids = talloc_zero_array(mem_ctx, struct lsa_SidPtr, num_query_sids);
535 if (sid_array.sids == NULL) {
536 return NT_STATUS_NO_MEMORY;
538 } else {
539 sid_array.sids = NULL;
542 for (i = 0; i < num_query_sids; i++) {
543 sid_array.sids[i].sid = dom_sid_dup(mem_ctx, &sids[total_sids++]);
544 if (sid_array.sids[i].sid == NULL) {
545 return NT_STATUS_NO_MEMORY;
548 sid_array.num_sids = num_query_sids;
550 /* do request */
551 status = dcerpc_samr_GetAliasMembership(b,
552 mem_ctx,
553 samr_policy,
554 &sid_array,
555 &alias_rids_query,
556 &result);
557 if (!NT_STATUS_IS_OK(status)) {
558 return status;
560 if (!NT_STATUS_IS_OK(result)) {
561 return result;
564 /* process output */
565 for (i = 0; i < alias_rids_query.count; i++) {
566 size_t na = num_aliases;
568 if (!add_rid_to_array_unique(mem_ctx,
569 alias_rids_query.ids[i],
570 &alias_rids,
571 &na)) {
572 return NT_STATUS_NO_MEMORY;
574 num_aliases = na;
577 num_queries++;
579 } while (total_sids < num_sids);
581 DEBUG(10,("rpc: rpc_lookup_useraliases: got %d aliases in %d queries "
582 "(rangesize: %d)\n", num_aliases, num_queries, rangesize));
584 *pnum_aliases = num_aliases;
585 *palias_rids = alias_rids;
587 return NT_STATUS_OK;
588 #undef MAX_SAM_ENTRIES_W2K
591 /* Lookup group membership given a rid. */
592 NTSTATUS rpc_lookup_groupmem(TALLOC_CTX *mem_ctx,
593 struct rpc_pipe_client *samr_pipe,
594 struct policy_handle *samr_policy,
595 const char *domain_name,
596 const struct dom_sid *domain_sid,
597 const struct dom_sid *group_sid,
598 enum lsa_SidType type,
599 uint32_t *pnum_names,
600 struct dom_sid **psid_mem,
601 char ***pnames,
602 uint32_t **pname_types)
604 struct policy_handle group_policy;
605 uint32_t group_rid;
606 uint32_t *rid_mem = NULL;
608 uint32_t num_names = 0;
609 uint32_t total_names = 0;
610 struct dom_sid *sid_mem = NULL;
611 char **names = NULL;
612 uint32_t *name_types = NULL;
614 struct lsa_Strings tmp_names;
615 struct samr_Ids tmp_types;
617 uint32_t j, r;
618 NTSTATUS status, result;
619 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
621 if (!sid_peek_check_rid(domain_sid, group_sid, &group_rid)) {
622 return NT_STATUS_UNSUCCESSFUL;
625 switch(type) {
626 case SID_NAME_DOM_GRP:
628 struct samr_RidAttrArray *rids = NULL;
630 status = dcerpc_samr_OpenGroup(b,
631 mem_ctx,
632 samr_policy,
633 SEC_FLAG_MAXIMUM_ALLOWED,
634 group_rid,
635 &group_policy,
636 &result);
637 if (!NT_STATUS_IS_OK(status)) {
638 return status;
640 if (!NT_STATUS_IS_OK(result)) {
641 return result;
645 * Step #1: Get a list of user rids that are the members of the group.
647 status = dcerpc_samr_QueryGroupMember(b,
648 mem_ctx,
649 &group_policy,
650 &rids,
651 &result);
653 NTSTATUS _result;
654 dcerpc_samr_Close(b, mem_ctx, &group_policy, &_result);
657 if (!NT_STATUS_IS_OK(status)) {
658 return status;
660 if (!NT_STATUS_IS_OK(result)) {
661 return result;
665 if (rids == NULL || rids->count == 0) {
666 pnum_names = 0;
667 pnames = NULL;
668 pname_types = NULL;
669 psid_mem = NULL;
671 return NT_STATUS_OK;
674 num_names = rids->count;
675 rid_mem = rids->rids;
677 break;
679 case SID_NAME_WKN_GRP:
680 case SID_NAME_ALIAS:
682 struct lsa_SidArray sid_array;
683 struct lsa_SidPtr sid_ptr;
684 struct samr_Ids rids_query;
686 sid_ptr.sid = dom_sid_dup(mem_ctx, group_sid);
687 if (sid_ptr.sid == NULL) {
688 return NT_STATUS_NO_MEMORY;
691 sid_array.num_sids = 1;
692 sid_array.sids = &sid_ptr;
694 status = dcerpc_samr_GetAliasMembership(b,
695 mem_ctx,
696 samr_policy,
697 &sid_array,
698 &rids_query,
699 &result);
700 if (!NT_STATUS_IS_OK(status)) {
701 return status;
703 if (!NT_STATUS_IS_OK(result)) {
704 return result;
707 if (rids_query.count == 0) {
708 pnum_names = 0;
709 pnames = NULL;
710 pname_types = NULL;
711 psid_mem = NULL;
713 return NT_STATUS_OK;
716 num_names = rids_query.count;
717 rid_mem = rids_query.ids;
719 break;
721 default:
722 return NT_STATUS_UNSUCCESSFUL;
726 * Step #2: Convert list of rids into list of usernames.
728 if (num_names > 0) {
729 names = talloc_zero_array(mem_ctx, char *, num_names);
730 name_types = talloc_zero_array(mem_ctx, uint32_t, num_names);
731 sid_mem = talloc_zero_array(mem_ctx, struct dom_sid, num_names);
732 if (names == NULL || name_types == NULL || sid_mem == NULL) {
733 return NT_STATUS_NO_MEMORY;
737 for (j = 0; j < num_names; j++) {
738 sid_compose(&sid_mem[j], domain_sid, rid_mem[j]);
741 status = dcerpc_samr_LookupRids(b,
742 mem_ctx,
743 samr_policy,
744 num_names,
745 rid_mem,
746 &tmp_names,
747 &tmp_types,
748 &result);
749 if (!NT_STATUS_IS_OK(status)) {
750 return status;
753 if (!NT_STATUS_IS_OK(result)) {
754 if (!NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
755 return result;
759 /* Copy result into array. The talloc system will take
760 care of freeing the temporary arrays later on. */
761 if (tmp_names.count != num_names) {
762 return NT_STATUS_INVALID_NETWORK_RESPONSE;
764 if (tmp_types.count != num_names) {
765 return NT_STATUS_INVALID_NETWORK_RESPONSE;
768 for (r = 0; r < tmp_names.count; r++) {
769 if (tmp_types.ids[r] == SID_NAME_UNKNOWN) {
770 continue;
772 if (total_names >= num_names) {
773 break;
775 names[total_names] = fill_domain_username_talloc(names,
776 domain_name,
777 tmp_names.names[r].string,
778 true);
779 if (names[total_names] == NULL) {
780 return NT_STATUS_NO_MEMORY;
782 name_types[total_names] = tmp_types.ids[r];
783 total_names++;
786 *pnum_names = total_names;
787 *pnames = names;
788 *pname_types = name_types;
789 *psid_mem = sid_mem;
791 return NT_STATUS_OK;
794 /* Find the sequence number for a domain */
795 NTSTATUS rpc_sequence_number(TALLOC_CTX *mem_ctx,
796 struct rpc_pipe_client *samr_pipe,
797 struct policy_handle *samr_policy,
798 const char *domain_name,
799 uint32_t *pseq)
801 union samr_DomainInfo *info = NULL;
802 bool got_seq_num = false;
803 NTSTATUS status, result;
804 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
806 /* query domain info */
807 status = dcerpc_samr_QueryDomainInfo(b,
808 mem_ctx,
809 samr_policy,
811 &info,
812 &result);
813 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
814 *pseq = info->info8.sequence_num;
815 got_seq_num = true;
816 goto seq_num;
819 /* retry with info-level 2 in case the dc does not support info-level 8
820 * (like all older samba2 and samba3 dc's) - Guenther */
821 status = dcerpc_samr_QueryDomainInfo(b,
822 mem_ctx,
823 samr_policy,
825 &info,
826 &result);
827 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
828 *pseq = info->general.sequence_num;
829 got_seq_num = true;
830 goto seq_num;
833 if (!NT_STATUS_IS_OK(status)) {
834 goto seq_num;
837 status = result;
839 seq_num:
840 if (got_seq_num) {
841 DEBUG(10,("domain_sequence_number: for domain %s is %u\n",
842 domain_name, (unsigned) *pseq));
843 } else {
844 DEBUG(10,("domain_sequence_number: failed to get sequence "
845 "number (%u) for domain %s\n",
846 (unsigned) *pseq, domain_name ));
847 status = NT_STATUS_OK;
850 return status;
853 /* Get a list of trusted domains */
854 NTSTATUS rpc_trusted_domains(TALLOC_CTX *mem_ctx,
855 struct rpc_pipe_client *lsa_pipe,
856 struct policy_handle *lsa_policy,
857 uint32_t *pnum_trusts,
858 struct netr_DomainTrust **ptrusts)
860 struct netr_DomainTrust *array = NULL;
861 uint32_t enum_ctx = 0;
862 uint32_t count = 0;
863 NTSTATUS status, result;
864 struct dcerpc_binding_handle *b = lsa_pipe->binding_handle;
866 do {
867 struct lsa_DomainList dom_list;
868 struct lsa_DomainListEx dom_list_ex;
869 bool has_ex = false;
870 uint32_t i;
873 * We don't run into deadlocks here, cause winbind_off() is
874 * called in the main function.
876 status = dcerpc_lsa_EnumTrustedDomainsEx(b,
877 mem_ctx,
878 lsa_policy,
879 &enum_ctx,
880 &dom_list_ex,
881 (uint32_t) -1,
882 &result);
883 if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_ERR(result) &&
884 dom_list_ex.count > 0) {
885 count += dom_list_ex.count;
886 has_ex = true;
887 } else {
888 status = dcerpc_lsa_EnumTrustDom(b,
889 mem_ctx,
890 lsa_policy,
891 &enum_ctx,
892 &dom_list,
893 (uint32_t) -1,
894 &result);
895 if (!NT_STATUS_IS_OK(status)) {
896 return status;
898 if (!NT_STATUS_IS_OK(result)) {
899 if (!NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
900 return result;
904 count += dom_list.count;
907 array = talloc_realloc(mem_ctx,
908 array,
909 struct netr_DomainTrust,
910 count);
911 if (array == NULL) {
912 return NT_STATUS_NO_MEMORY;
915 for (i = 0; i < count; i++) {
916 struct netr_DomainTrust *trust = &array[i];
917 struct dom_sid *sid;
919 ZERO_STRUCTP(trust);
921 sid = talloc(array, struct dom_sid);
922 if (sid == NULL) {
923 return NT_STATUS_NO_MEMORY;
926 if (has_ex) {
927 trust->netbios_name = talloc_move(array,
928 &dom_list_ex.domains[i].netbios_name.string);
929 trust->dns_name = talloc_move(array,
930 &dom_list_ex.domains[i].domain_name.string);
931 if (dom_list_ex.domains[i].sid == NULL) {
932 DEBUG(0, ("Trusted Domain %s has no SID, aborting!\n", trust->dns_name));
933 return NT_STATUS_INVALID_NETWORK_RESPONSE;
935 sid_copy(sid, dom_list_ex.domains[i].sid);
936 } else {
937 trust->netbios_name = talloc_move(array,
938 &dom_list.domains[i].name.string);
939 trust->dns_name = NULL;
941 if (dom_list.domains[i].sid == NULL) {
942 DEBUG(0, ("Trusted Domain %s has no SID, aborting!\n", trust->netbios_name));
943 return NT_STATUS_INVALID_NETWORK_RESPONSE;
946 sid_copy(sid, dom_list.domains[i].sid);
949 trust->sid = sid;
951 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
953 *pnum_trusts = count;
954 *ptrusts = array;
956 return NT_STATUS_OK;
959 static NTSTATUS rpc_try_lookup_sids3(TALLOC_CTX *mem_ctx,
960 struct winbindd_domain *domain,
961 struct rpc_pipe_client *cli,
962 struct lsa_SidArray *sids,
963 struct lsa_RefDomainList **pdomains,
964 struct lsa_TransNameArray **pnames)
966 struct lsa_TransNameArray2 lsa_names2;
967 struct lsa_TransNameArray *names = *pnames;
968 uint32_t i, count = 0;
969 NTSTATUS status, result;
971 ZERO_STRUCT(lsa_names2);
972 status = dcerpc_lsa_LookupSids3(cli->binding_handle,
973 mem_ctx,
974 sids,
975 pdomains,
976 &lsa_names2,
977 LSA_LOOKUP_NAMES_ALL,
978 &count,
979 LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES,
980 LSA_CLIENT_REVISION_2,
981 &result);
982 if (!NT_STATUS_IS_OK(status)) {
983 return status;
985 if (NT_STATUS_LOOKUP_ERR(result)) {
986 return result;
988 if (sids->num_sids != lsa_names2.count) {
989 return NT_STATUS_INVALID_NETWORK_RESPONSE;
992 names->count = lsa_names2.count;
993 names->names = talloc_array(names, struct lsa_TranslatedName,
994 names->count);
995 if (names->names == NULL) {
996 return NT_STATUS_NO_MEMORY;
998 for (i=0; i<names->count; i++) {
999 names->names[i].sid_type = lsa_names2.names[i].sid_type;
1000 names->names[i].name.string = talloc_move(
1001 names->names, &lsa_names2.names[i].name.string);
1002 names->names[i].sid_index = lsa_names2.names[i].sid_index;
1004 if (names->names[i].sid_index == UINT32_MAX) {
1005 continue;
1007 if ((*pdomains) == NULL) {
1008 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1010 if (names->names[i].sid_index >= (*pdomains)->count) {
1011 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1014 return NT_STATUS_OK;
1017 NTSTATUS rpc_lookup_sids(TALLOC_CTX *mem_ctx,
1018 struct winbindd_domain *domain,
1019 struct lsa_SidArray *sids,
1020 struct lsa_RefDomainList **pdomains,
1021 struct lsa_TransNameArray **pnames)
1023 struct lsa_TransNameArray *names = *pnames;
1024 struct rpc_pipe_client *cli = NULL;
1025 struct policy_handle lsa_policy;
1026 uint32_t count;
1027 uint32_t i;
1028 NTSTATUS status, result;
1030 status = cm_connect_lsat(domain, mem_ctx, &cli, &lsa_policy);
1031 if (!NT_STATUS_IS_OK(status)) {
1032 return status;
1035 if (cli->transport->transport == NCACN_IP_TCP) {
1036 return rpc_try_lookup_sids3(mem_ctx, domain, cli, sids,
1037 pdomains, pnames);
1040 status = dcerpc_lsa_LookupSids(cli->binding_handle, mem_ctx,
1041 &lsa_policy, sids, pdomains,
1042 names, LSA_LOOKUP_NAMES_ALL,
1043 &count, &result);
1044 if (!NT_STATUS_IS_OK(status)) {
1045 return status;
1047 if (NT_STATUS_LOOKUP_ERR(result)) {
1048 return result;
1051 if (sids->num_sids != names->count) {
1052 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1055 for (i=0; i < names->count; i++) {
1056 if (names->names[i].sid_index == UINT32_MAX) {
1057 continue;
1059 if ((*pdomains) == NULL) {
1060 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1062 if (names->names[i].sid_index >= (*pdomains)->count) {
1063 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1067 return NT_STATUS_OK;