source: vendor/3.6.0/source3/winbindd/winbindd_rpc.c

Last change on this file was 740, checked in by Silvan Scherrer, 13 years ago

Samba Server: update vendor to 3.6.0

File size: 27.9 KB
Line 
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
36/* Query display info for a domain */
37NTSTATUS rpc_query_user_list(TALLOC_CTX *mem_ctx,
38 struct rpc_pipe_client *samr_pipe,
39 struct policy_handle *samr_policy,
40 const struct dom_sid *domain_sid,
41 uint32_t *pnum_info,
42 struct wbint_userinfo **pinfo)
43{
44 struct wbint_userinfo *info = NULL;
45 uint32_t num_info = 0;
46 uint32_t loop_count = 0;
47 uint32_t start_idx = 0;
48 uint32_t i = 0;
49 NTSTATUS status, result;
50 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
51
52 *pnum_info = 0;
53
54 do {
55 uint32_t j;
56 uint32_t num_dom_users;
57 uint32_t max_entries, max_size;
58 uint32_t total_size, returned_size;
59 union samr_DispInfo disp_info;
60
61 dcerpc_get_query_dispinfo_params(loop_count,
62 &max_entries,
63 &max_size);
64
65 status = dcerpc_samr_QueryDisplayInfo(b,
66 mem_ctx,
67 samr_policy,
68 1, /* level */
69 start_idx,
70 max_entries,
71 max_size,
72 &total_size,
73 &returned_size,
74 &disp_info,
75 &result);
76 if (!NT_STATUS_IS_OK(status)) {
77 return status;
78 }
79 if (!NT_STATUS_IS_OK(result)) {
80 if (!NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
81 return result;
82 }
83 }
84
85 /* increment required start query values */
86 start_idx += disp_info.info1.count;
87 loop_count++;
88 num_dom_users = disp_info.info1.count;
89
90 num_info += num_dom_users;
91
92 info = TALLOC_REALLOC_ARRAY(mem_ctx,
93 info,
94 struct wbint_userinfo,
95 num_info);
96 if (info == NULL) {
97 return NT_STATUS_NO_MEMORY;
98 }
99
100 for (j = 0; j < num_dom_users; i++, j++) {
101 uint32_t rid = disp_info.info1.entries[j].rid;
102 struct samr_DispEntryGeneral *src;
103 struct wbint_userinfo *dst;
104
105 src = &(disp_info.info1.entries[j]);
106 dst = &(info[i]);
107
108 dst->acct_name = talloc_strdup(info,
109 src->account_name.string);
110 if (dst->acct_name == NULL) {
111 return NT_STATUS_NO_MEMORY;
112 }
113
114 dst->full_name = talloc_strdup(info, src->full_name.string);
115 if ((src->full_name.string != NULL) &&
116 (dst->full_name == NULL))
117 {
118 return NT_STATUS_NO_MEMORY;
119 }
120
121 dst->homedir = NULL;
122 dst->shell = NULL;
123
124 sid_compose(&dst->user_sid, domain_sid, rid);
125
126 /* For the moment we set the primary group for
127 every user to be the Domain Users group.
128 There are serious problems with determining
129 the actual primary group for large domains.
130 This should really be made into a 'winbind
131 force group' smb.conf parameter or
132 something like that. */
133 sid_compose(&dst->group_sid, domain_sid,
134 DOMAIN_RID_USERS);
135 }
136 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
137
138 *pnum_info = num_info;
139 *pinfo = info;
140
141 return NT_STATUS_OK;
142}
143
144/* List all domain groups */
145NTSTATUS rpc_enum_dom_groups(TALLOC_CTX *mem_ctx,
146 struct rpc_pipe_client *samr_pipe,
147 struct policy_handle *samr_policy,
148 uint32_t *pnum_info,
149 struct wb_acct_info **pinfo)
150{
151 struct wb_acct_info *info = NULL;
152 uint32_t start = 0;
153 uint32_t num_info = 0;
154 NTSTATUS status, result;
155 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
156
157 *pnum_info = 0;
158
159 do {
160 struct samr_SamArray *sam_array = NULL;
161 uint32_t count = 0;
162 uint32_t g;
163
164 /* start is updated by this call. */
165 status = dcerpc_samr_EnumDomainGroups(b,
166 mem_ctx,
167 samr_policy,
168 &start,
169 &sam_array,
170 0xFFFF, /* buffer size? */
171 &count,
172 &result);
173 if (!NT_STATUS_IS_OK(status)) {
174 return status;
175 }
176 if (!NT_STATUS_IS_OK(result)) {
177 if (!NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
178 DEBUG(2,("query_user_list: failed to enum domain groups: %s\n",
179 nt_errstr(result)));
180 return result;
181 }
182 }
183
184 info = TALLOC_REALLOC_ARRAY(mem_ctx,
185 info,
186 struct wb_acct_info,
187 num_info + count);
188 if (info == NULL) {
189 return NT_STATUS_NO_MEMORY;
190 }
191
192 for (g = 0; g < count; g++) {
193 fstrcpy(info[num_info + g].acct_name,
194 sam_array->entries[g].name.string);
195
196 info[num_info + g].rid = sam_array->entries[g].idx;
197 }
198
199 num_info += count;
200 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
201
202 *pnum_info = num_info;
203 *pinfo = info;
204
205 return NT_STATUS_OK;
206}
207
208NTSTATUS rpc_enum_local_groups(TALLOC_CTX *mem_ctx,
209 struct rpc_pipe_client *samr_pipe,
210 struct policy_handle *samr_policy,
211 uint32_t *pnum_info,
212 struct wb_acct_info **pinfo)
213{
214 struct wb_acct_info *info = NULL;
215 uint32_t num_info = 0;
216 NTSTATUS status, result;
217 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
218
219 *pnum_info = 0;
220
221 do {
222 struct samr_SamArray *sam_array = NULL;
223 uint32_t count = 0;
224 uint32_t start = num_info;
225 uint32_t g;
226
227 status = dcerpc_samr_EnumDomainAliases(b,
228 mem_ctx,
229 samr_policy,
230 &start,
231 &sam_array,
232 0xFFFF, /* buffer size? */
233 &count,
234 &result);
235 if (!NT_STATUS_IS_OK(status)) {
236 return status;
237 }
238 if (!NT_STATUS_IS_OK(result)) {
239 if (!NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
240 return result;
241 }
242 }
243
244 info = TALLOC_REALLOC_ARRAY(mem_ctx,
245 info,
246 struct wb_acct_info,
247 num_info + count);
248 if (info == NULL) {
249 return NT_STATUS_NO_MEMORY;
250 }
251
252 for (g = 0; g < count; g++) {
253 fstrcpy(info[num_info + g].acct_name,
254 sam_array->entries[g].name.string);
255 info[num_info + g].rid = sam_array->entries[g].idx;
256 }
257
258 num_info += count;
259 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
260
261 *pnum_info = num_info;
262 *pinfo = info;
263
264 return NT_STATUS_OK;
265}
266
267/* convert a single name to a sid in a domain */
268NTSTATUS rpc_name_to_sid(TALLOC_CTX *mem_ctx,
269 struct rpc_pipe_client *lsa_pipe,
270 struct policy_handle *lsa_policy,
271 const char *domain_name,
272 const char *name,
273 uint32_t flags,
274 struct dom_sid *sid,
275 enum lsa_SidType *type)
276{
277 enum lsa_SidType *types = NULL;
278 struct dom_sid *sids = NULL;
279 char *full_name = NULL;
280 char *mapped_name = NULL;
281 NTSTATUS status;
282
283 if (name == NULL || name[0] == '\0') {
284 full_name = talloc_asprintf(mem_ctx, "%s", domain_name);
285 } else if (domain_name == NULL || domain_name[0] == '\0') {
286 full_name = talloc_asprintf(mem_ctx, "%s", name);
287 } else {
288 full_name = talloc_asprintf(mem_ctx, "%s\\%s", domain_name, name);
289 }
290
291 if (full_name == NULL) {
292 return NT_STATUS_NO_MEMORY;
293 }
294
295 status = normalize_name_unmap(mem_ctx, full_name, &mapped_name);
296 /* Reset the full_name pointer if we mapped anything */
297 if (NT_STATUS_IS_OK(status) ||
298 NT_STATUS_EQUAL(status, NT_STATUS_FILE_RENAMED)) {
299 full_name = mapped_name;
300 }
301
302 DEBUG(3,("name_to_sid: %s for domain %s\n",
303 full_name ? full_name : "", domain_name ));
304
305 /*
306 * We don't run into deadlocks here, cause winbind_off() is
307 * called in the main function.
308 */
309 status = rpccli_lsa_lookup_names(lsa_pipe,
310 mem_ctx,
311 lsa_policy,
312 1, /* num_names */
313 (const char **) &full_name,
314 NULL, /* domains */
315 1, /* level */
316 &sids,
317 &types);
318 if (!NT_STATUS_IS_OK(status)) {
319 DEBUG(2,("name_to_sid: failed to lookup name: %s\n",
320 nt_errstr(status)));
321 return status;
322 }
323
324 sid_copy(sid, &sids[0]);
325 *type = types[0];
326
327 return NT_STATUS_OK;
328}
329
330/* Convert a domain SID to a user or group name */
331NTSTATUS rpc_sid_to_name(TALLOC_CTX *mem_ctx,
332 struct rpc_pipe_client *lsa_pipe,
333 struct policy_handle *lsa_policy,
334 struct winbindd_domain *domain,
335 const struct dom_sid *sid,
336 char **pdomain_name,
337 char **pname,
338 enum lsa_SidType *ptype)
339{
340 char *mapped_name = NULL;
341 char **domains = NULL;
342 char **names = NULL;
343 enum lsa_SidType *types = NULL;
344 NTSTATUS map_status;
345 NTSTATUS status;
346
347 status = rpccli_lsa_lookup_sids(lsa_pipe,
348 mem_ctx,
349 lsa_policy,
350 1, /* num_sids */
351 sid,
352 &domains,
353 &names,
354 &types);
355 if (!NT_STATUS_IS_OK(status)) {
356 DEBUG(2,("sid_to_name: failed to lookup sids: %s\n",
357 nt_errstr(status)));
358 return status;
359 }
360
361 *ptype = (enum lsa_SidType) types[0];
362
363 map_status = normalize_name_map(mem_ctx,
364 domain,
365 *pname,
366 &mapped_name);
367 if (NT_STATUS_IS_OK(map_status) ||
368 NT_STATUS_EQUAL(map_status, NT_STATUS_FILE_RENAMED)) {
369 *pname = talloc_strdup(mem_ctx, mapped_name);
370 DEBUG(5,("returning mapped name -- %s\n", *pname));
371 } else {
372 *pname = talloc_strdup(mem_ctx, names[0]);
373 }
374 if (*pname == NULL) {
375 return NT_STATUS_NO_MEMORY;
376 }
377
378 *pdomain_name = talloc_strdup(mem_ctx, domains[0]);
379 if (*pdomain_name == NULL) {
380 return NT_STATUS_NO_MEMORY;
381 }
382
383 return NT_STATUS_OK;
384}
385
386/* Convert a bunch of rids to user or group names */
387NTSTATUS rpc_rids_to_names(TALLOC_CTX *mem_ctx,
388 struct rpc_pipe_client *lsa_pipe,
389 struct policy_handle *lsa_policy,
390 struct winbindd_domain *domain,
391 const struct dom_sid *sid,
392 uint32_t *rids,
393 size_t num_rids,
394 char **pdomain_name,
395 char ***pnames,
396 enum lsa_SidType **ptypes)
397{
398 enum lsa_SidType *types = NULL;
399 char *domain_name = NULL;
400 char **domains = NULL;
401 char **names = NULL;
402 struct dom_sid *sids;
403 size_t i;
404 NTSTATUS status;
405
406 if (num_rids > 0) {
407 sids = TALLOC_ARRAY(mem_ctx, struct dom_sid, num_rids);
408 if (sids == NULL) {
409 return NT_STATUS_NO_MEMORY;
410 }
411 } else {
412 sids = NULL;
413 }
414
415 for (i = 0; i < num_rids; i++) {
416 if (!sid_compose(&sids[i], sid, rids[i])) {
417 return NT_STATUS_INTERNAL_ERROR;
418 }
419 }
420
421 status = rpccli_lsa_lookup_sids(lsa_pipe,
422 mem_ctx,
423 lsa_policy,
424 num_rids,
425 sids,
426 &domains,
427 &names,
428 &types);
429 if (!NT_STATUS_IS_OK(status) &&
430 !NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
431 DEBUG(2,("rids_to_names: failed to lookup sids: %s\n",
432 nt_errstr(status)));
433 return status;
434 }
435
436 for (i = 0; i < num_rids; i++) {
437 char *mapped_name = NULL;
438 NTSTATUS map_status;
439
440 if (types[i] != SID_NAME_UNKNOWN) {
441 map_status = normalize_name_map(mem_ctx,
442 domain,
443 names[i],
444 &mapped_name);
445 if (NT_STATUS_IS_OK(map_status) ||
446 NT_STATUS_EQUAL(map_status, NT_STATUS_FILE_RENAMED)) {
447 TALLOC_FREE(names[i]);
448 names[i] = talloc_strdup(names, mapped_name);
449 if (names[i] == NULL) {
450 return NT_STATUS_NO_MEMORY;
451 }
452 }
453
454 domain_name = domains[i];
455 }
456 }
457
458 *pdomain_name = domain_name;
459 *ptypes = types;
460 *pnames = names;
461
462 return NT_STATUS_OK;
463}
464
465/* Lookup user information from a rid or username. */
466NTSTATUS rpc_query_user(TALLOC_CTX *mem_ctx,
467 struct rpc_pipe_client *samr_pipe,
468 struct policy_handle *samr_policy,
469 const struct dom_sid *domain_sid,
470 const struct dom_sid *user_sid,
471 struct wbint_userinfo *user_info)
472{
473 struct policy_handle user_policy;
474 union samr_UserInfo *info = NULL;
475 uint32_t user_rid;
476 NTSTATUS status, result;
477 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
478
479 if (!sid_peek_check_rid(domain_sid, user_sid, &user_rid)) {
480 return NT_STATUS_UNSUCCESSFUL;
481 }
482
483 /* Get user handle */
484 status = dcerpc_samr_OpenUser(b,
485 mem_ctx,
486 samr_policy,
487 SEC_FLAG_MAXIMUM_ALLOWED,
488 user_rid,
489 &user_policy,
490 &result);
491 if (!NT_STATUS_IS_OK(status)) {
492 return status;
493 }
494 if (!NT_STATUS_IS_OK(result)) {
495 return result;
496 }
497
498 /* Get user info */
499 status = dcerpc_samr_QueryUserInfo(b,
500 mem_ctx,
501 &user_policy,
502 0x15,
503 &info,
504 &result);
505 {
506 NTSTATUS _result;
507 dcerpc_samr_Close(b, mem_ctx, &user_policy, &_result);
508 }
509 if (!NT_STATUS_IS_OK(status)) {
510 return status;
511 }
512 if (!NT_STATUS_IS_OK(result)) {
513 return result;
514 }
515
516 sid_compose(&user_info->user_sid, domain_sid, user_rid);
517 sid_compose(&user_info->group_sid, domain_sid,
518 info->info21.primary_gid);
519
520 user_info->acct_name = talloc_strdup(user_info,
521 info->info21.account_name.string);
522 if (user_info->acct_name == NULL) {
523 return NT_STATUS_NO_MEMORY;
524 }
525
526 user_info->full_name = talloc_strdup(user_info,
527 info->info21.full_name.string);
528 if ((info->info21.full_name.string != NULL) &&
529 (user_info->acct_name == NULL))
530 {
531 return NT_STATUS_NO_MEMORY;
532 }
533
534 user_info->homedir = NULL;
535 user_info->shell = NULL;
536 user_info->primary_gid = (gid_t)-1;
537
538 return NT_STATUS_OK;
539}
540
541/* Lookup groups a user is a member of. */
542NTSTATUS rpc_lookup_usergroups(TALLOC_CTX *mem_ctx,
543 struct rpc_pipe_client *samr_pipe,
544 struct policy_handle *samr_policy,
545 const struct dom_sid *domain_sid,
546 const struct dom_sid *user_sid,
547 uint32_t *pnum_groups,
548 struct dom_sid **puser_grpsids)
549{
550 struct policy_handle user_policy;
551 struct samr_RidWithAttributeArray *rid_array = NULL;
552 struct dom_sid *user_grpsids = NULL;
553 uint32_t num_groups = 0, i;
554 uint32_t user_rid;
555 NTSTATUS status, result;
556 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
557
558 if (!sid_peek_check_rid(domain_sid, user_sid, &user_rid)) {
559 return NT_STATUS_UNSUCCESSFUL;
560 }
561
562 /* Get user handle */
563 status = dcerpc_samr_OpenUser(b,
564 mem_ctx,
565 samr_policy,
566 SEC_FLAG_MAXIMUM_ALLOWED,
567 user_rid,
568 &user_policy,
569 &result);
570 if (!NT_STATUS_IS_OK(status)) {
571 return status;
572 }
573 if (!NT_STATUS_IS_OK(result)) {
574 return result;
575 }
576
577 /* Query user rids */
578 status = dcerpc_samr_GetGroupsForUser(b,
579 mem_ctx,
580 &user_policy,
581 &rid_array,
582 &result);
583 num_groups = rid_array->count;
584
585 {
586 NTSTATUS _result;
587 dcerpc_samr_Close(b, mem_ctx, &user_policy, &_result);
588 }
589
590 if (!NT_STATUS_IS_OK(status)) {
591 return status;
592 }
593 if (!NT_STATUS_IS_OK(result) || num_groups == 0) {
594 return result;
595 }
596
597 user_grpsids = TALLOC_ARRAY(mem_ctx, struct dom_sid, num_groups);
598 if (user_grpsids == NULL) {
599 status = NT_STATUS_NO_MEMORY;
600 return status;
601 }
602
603 for (i = 0; i < num_groups; i++) {
604 sid_compose(&(user_grpsids[i]), domain_sid,
605 rid_array->rids[i].rid);
606 }
607
608 *pnum_groups = num_groups;
609
610 *puser_grpsids = user_grpsids;
611
612 return NT_STATUS_OK;
613}
614
615NTSTATUS rpc_lookup_useraliases(TALLOC_CTX *mem_ctx,
616 struct rpc_pipe_client *samr_pipe,
617 struct policy_handle *samr_policy,
618 uint32_t num_sids,
619 const struct dom_sid *sids,
620 uint32_t *pnum_aliases,
621 uint32_t **palias_rids)
622{
623#define MAX_SAM_ENTRIES_W2K 0x400 /* 1024 */
624 uint32_t num_query_sids = 0;
625 uint32_t num_queries = 1;
626 uint32_t num_aliases = 0;
627 uint32_t total_sids = 0;
628 uint32_t *alias_rids = NULL;
629 uint32_t rangesize = MAX_SAM_ENTRIES_W2K;
630 uint32_t i;
631 struct samr_Ids alias_rids_query;
632 NTSTATUS status, result;
633 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
634
635 do {
636 /* prepare query */
637 struct lsa_SidArray sid_array;
638
639 ZERO_STRUCT(sid_array);
640
641 num_query_sids = MIN(num_sids - total_sids, rangesize);
642
643 DEBUG(10,("rpc: lookup_useraliases: entering query %d for %d sids\n",
644 num_queries, num_query_sids));
645
646 if (num_query_sids) {
647 sid_array.sids = TALLOC_ZERO_ARRAY(mem_ctx, struct lsa_SidPtr, num_query_sids);
648 if (sid_array.sids == NULL) {
649 return NT_STATUS_NO_MEMORY;
650 }
651 } else {
652 sid_array.sids = NULL;
653 }
654
655 for (i = 0; i < num_query_sids; i++) {
656 sid_array.sids[i].sid = dom_sid_dup(mem_ctx, &sids[total_sids++]);
657 if (sid_array.sids[i].sid == NULL) {
658 return NT_STATUS_NO_MEMORY;
659 }
660 }
661 sid_array.num_sids = num_query_sids;
662
663 /* do request */
664 status = dcerpc_samr_GetAliasMembership(b,
665 mem_ctx,
666 samr_policy,
667 &sid_array,
668 &alias_rids_query,
669 &result);
670 if (!NT_STATUS_IS_OK(status)) {
671 return status;
672 }
673 if (!NT_STATUS_IS_OK(result)) {
674 return result;
675 }
676
677 /* process output */
678 for (i = 0; i < alias_rids_query.count; i++) {
679 size_t na = num_aliases;
680
681 if (!add_rid_to_array_unique(mem_ctx,
682 alias_rids_query.ids[i],
683 &alias_rids,
684 &na)) {
685 return NT_STATUS_NO_MEMORY;
686 }
687 num_aliases = na;
688 }
689
690 num_queries++;
691
692 } while (total_sids < num_sids);
693
694 DEBUG(10,("rpc: rpc_lookup_useraliases: got %d aliases in %d queries "
695 "(rangesize: %d)\n", num_aliases, num_queries, rangesize));
696
697 *pnum_aliases = num_aliases;
698 *palias_rids = alias_rids;
699
700 return NT_STATUS_OK;
701#undef MAX_SAM_ENTRIES_W2K
702}
703
704/* Lookup group membership given a rid. */
705NTSTATUS rpc_lookup_groupmem(TALLOC_CTX *mem_ctx,
706 struct rpc_pipe_client *samr_pipe,
707 struct policy_handle *samr_policy,
708 const char *domain_name,
709 const struct dom_sid *domain_sid,
710 const struct dom_sid *group_sid,
711 enum lsa_SidType type,
712 uint32_t *pnum_names,
713 struct dom_sid **psid_mem,
714 char ***pnames,
715 uint32_t **pname_types)
716{
717 struct policy_handle group_policy;
718 uint32_t group_rid;
719 uint32_t *rid_mem = NULL;
720
721 uint32_t num_names = 0;
722 uint32_t total_names = 0;
723 struct dom_sid *sid_mem = NULL;
724 char **names = NULL;
725 uint32_t *name_types = NULL;
726
727 struct lsa_Strings tmp_names;
728 struct samr_Ids tmp_types;
729
730 uint32_t j, r;
731 NTSTATUS status, result;
732 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
733
734 if (!sid_peek_check_rid(domain_sid, group_sid, &group_rid)) {
735 return NT_STATUS_UNSUCCESSFUL;
736 }
737
738 switch(type) {
739 case SID_NAME_DOM_GRP:
740 {
741 struct samr_RidAttrArray *rids = NULL;
742
743 status = dcerpc_samr_OpenGroup(b,
744 mem_ctx,
745 samr_policy,
746 SEC_FLAG_MAXIMUM_ALLOWED,
747 group_rid,
748 &group_policy,
749 &result);
750 if (!NT_STATUS_IS_OK(status)) {
751 return status;
752 }
753 if (!NT_STATUS_IS_OK(result)) {
754 return result;
755 }
756
757 /*
758 * Step #1: Get a list of user rids that are the members of the group.
759 */
760 status = dcerpc_samr_QueryGroupMember(b,
761 mem_ctx,
762 &group_policy,
763 &rids,
764 &result);
765 {
766 NTSTATUS _result;
767 dcerpc_samr_Close(b, mem_ctx, &group_policy, &_result);
768 }
769
770 if (!NT_STATUS_IS_OK(status)) {
771 return status;
772 }
773 if (!NT_STATUS_IS_OK(result)) {
774 return result;
775 }
776
777
778 if (rids == NULL || rids->count == 0) {
779 pnum_names = 0;
780 pnames = NULL;
781 pname_types = NULL;
782 psid_mem = NULL;
783
784 return NT_STATUS_OK;
785 }
786
787 num_names = rids->count;
788 rid_mem = rids->rids;
789
790 break;
791 }
792 case SID_NAME_WKN_GRP:
793 case SID_NAME_ALIAS:
794 {
795 struct lsa_SidArray sid_array;
796 struct lsa_SidPtr sid_ptr;
797 struct samr_Ids rids_query;
798
799 sid_ptr.sid = dom_sid_dup(mem_ctx, group_sid);
800 if (sid_ptr.sid == NULL) {
801 return NT_STATUS_NO_MEMORY;
802 }
803
804 sid_array.num_sids = 1;
805 sid_array.sids = &sid_ptr;
806
807 status = dcerpc_samr_GetAliasMembership(b,
808 mem_ctx,
809 samr_policy,
810 &sid_array,
811 &rids_query,
812 &result);
813 if (!NT_STATUS_IS_OK(status)) {
814 return status;
815 }
816 if (!NT_STATUS_IS_OK(result)) {
817 return result;
818 }
819
820 if (rids_query.count == 0) {
821 pnum_names = 0;
822 pnames = NULL;
823 pname_types = NULL;
824 psid_mem = NULL;
825
826 return NT_STATUS_OK;
827 }
828
829 num_names = rids_query.count;
830 rid_mem = rids_query.ids;
831
832 break;
833 }
834 default:
835 return NT_STATUS_UNSUCCESSFUL;
836 }
837
838 /*
839 * Step #2: Convert list of rids into list of usernames.
840 */
841 if (num_names > 0) {
842 names = TALLOC_ZERO_ARRAY(mem_ctx, char *, num_names);
843 name_types = TALLOC_ZERO_ARRAY(mem_ctx, uint32_t, num_names);
844 sid_mem = TALLOC_ZERO_ARRAY(mem_ctx, struct dom_sid, num_names);
845 if (names == NULL || name_types == NULL || sid_mem == NULL) {
846 return NT_STATUS_NO_MEMORY;
847 }
848 }
849
850 for (j = 0; j < num_names; j++) {
851 sid_compose(&sid_mem[j], domain_sid, rid_mem[j]);
852 }
853
854 status = dcerpc_samr_LookupRids(b,
855 mem_ctx,
856 samr_policy,
857 num_names,
858 rid_mem,
859 &tmp_names,
860 &tmp_types,
861 &result);
862 if (!NT_STATUS_IS_OK(status)) {
863 return status;
864 }
865
866 if (!NT_STATUS_IS_OK(result)) {
867 if (!NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
868 return result;
869 }
870 }
871
872 /* Copy result into array. The talloc system will take
873 care of freeing the temporary arrays later on. */
874 if (tmp_names.count != tmp_types.count) {
875 return NT_STATUS_UNSUCCESSFUL;
876 }
877
878 for (r = 0; r < tmp_names.count; r++) {
879 if (tmp_types.ids[r] == SID_NAME_UNKNOWN) {
880 continue;
881 }
882 names[total_names] = fill_domain_username_talloc(names,
883 domain_name,
884 tmp_names.names[r].string,
885 true);
886 if (names[total_names] == NULL) {
887 return NT_STATUS_NO_MEMORY;
888 }
889 name_types[total_names] = tmp_types.ids[r];
890 total_names++;
891 }
892
893 *pnum_names = total_names;
894 *pnames = names;
895 *pname_types = name_types;
896 *psid_mem = sid_mem;
897
898 return NT_STATUS_OK;
899}
900
901/* Find the sequence number for a domain */
902NTSTATUS rpc_sequence_number(TALLOC_CTX *mem_ctx,
903 struct rpc_pipe_client *samr_pipe,
904 struct policy_handle *samr_policy,
905 const char *domain_name,
906 uint32_t *pseq)
907{
908 union samr_DomainInfo *info = NULL;
909 bool got_seq_num = false;
910 NTSTATUS status, result;
911 struct dcerpc_binding_handle *b = samr_pipe->binding_handle;
912
913 /* query domain info */
914 status = dcerpc_samr_QueryDomainInfo(b,
915 mem_ctx,
916 samr_policy,
917 8,
918 &info,
919 &result);
920 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
921 *pseq = info->info8.sequence_num;
922 got_seq_num = true;
923 goto seq_num;
924 }
925
926 /* retry with info-level 2 in case the dc does not support info-level 8
927 * (like all older samba2 and samba3 dc's) - Guenther */
928 status = dcerpc_samr_QueryDomainInfo(b,
929 mem_ctx,
930 samr_policy,
931 2,
932 &info,
933 &result);
934 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
935 *pseq = info->general.sequence_num;
936 got_seq_num = true;
937 goto seq_num;
938 }
939
940 if (!NT_STATUS_IS_OK(status)) {
941 goto seq_num;
942 }
943
944 status = result;
945
946seq_num:
947 if (got_seq_num) {
948 DEBUG(10,("domain_sequence_number: for domain %s is %u\n",
949 domain_name, (unsigned) *pseq));
950 } else {
951 DEBUG(10,("domain_sequence_number: failed to get sequence "
952 "number (%u) for domain %s\n",
953 (unsigned) *pseq, domain_name ));
954 status = NT_STATUS_OK;
955 }
956
957 return status;
958}
959
960/* Get a list of trusted domains */
961NTSTATUS rpc_trusted_domains(TALLOC_CTX *mem_ctx,
962 struct rpc_pipe_client *lsa_pipe,
963 struct policy_handle *lsa_policy,
964 uint32_t *pnum_trusts,
965 struct netr_DomainTrust **ptrusts)
966{
967 struct netr_DomainTrust *array = NULL;
968 uint32_t enum_ctx = 0;
969 uint32_t count = 0;
970 NTSTATUS status, result;
971 struct dcerpc_binding_handle *b = lsa_pipe->binding_handle;
972
973 do {
974 struct lsa_DomainList dom_list;
975 uint32_t start_idx;
976 uint32_t i;
977
978 /*
979 * We don't run into deadlocks here, cause winbind_off() is
980 * called in the main function.
981 */
982 status = dcerpc_lsa_EnumTrustDom(b,
983 mem_ctx,
984 lsa_policy,
985 &enum_ctx,
986 &dom_list,
987 (uint32_t) -1,
988 &result);
989 if (!NT_STATUS_IS_OK(status)) {
990 return status;
991 }
992 if (!NT_STATUS_IS_OK(result)) {
993 if (!NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
994 return result;
995 }
996 }
997
998 start_idx = count;
999 count += dom_list.count;
1000
1001 array = talloc_realloc(mem_ctx,
1002 array,
1003 struct netr_DomainTrust,
1004 count);
1005 if (array == NULL) {
1006 return NT_STATUS_NO_MEMORY;
1007 }
1008
1009 for (i = 0; i < dom_list.count; i++) {
1010 struct netr_DomainTrust *trust = &array[i];
1011 struct dom_sid *sid;
1012
1013 ZERO_STRUCTP(trust);
1014
1015 trust->netbios_name = talloc_move(array,
1016 &dom_list.domains[i].name.string);
1017 trust->dns_name = NULL;
1018
1019 sid = talloc(array, struct dom_sid);
1020 if (sid == NULL) {
1021 return NT_STATUS_NO_MEMORY;
1022 }
1023 sid_copy(sid, dom_list.domains[i].sid);
1024 trust->sid = sid;
1025 }
1026 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
1027
1028 *pnum_trusts = count;
1029 *ptrusts = array;
1030
1031 return NT_STATUS_OK;
1032}
1033
1034static NTSTATUS rpc_try_lookup_sids3(TALLOC_CTX *mem_ctx,
1035 struct winbindd_domain *domain,
1036 struct lsa_SidArray *sids,
1037 struct lsa_RefDomainList **pdomains,
1038 struct lsa_TransNameArray **pnames)
1039{
1040 struct lsa_TransNameArray2 lsa_names2;
1041 struct lsa_TransNameArray *names;
1042 uint32_t i, count;
1043 struct rpc_pipe_client *cli;
1044 NTSTATUS status, result;
1045
1046 status = cm_connect_lsa_tcp(domain, talloc_tos(), &cli);
1047 if (!NT_STATUS_IS_OK(status)) {
1048 domain->can_do_ncacn_ip_tcp = false;
1049 return status;
1050 }
1051
1052 ZERO_STRUCT(lsa_names2);
1053 status = dcerpc_lsa_LookupSids3(cli->binding_handle,
1054 mem_ctx,
1055 sids,
1056 pdomains,
1057 &lsa_names2,
1058 LSA_LOOKUP_NAMES_ALL,
1059 &count,
1060 LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES,
1061 LSA_CLIENT_REVISION_2,
1062 &result);
1063 if (!NT_STATUS_IS_OK(status)) {
1064 return status;
1065 }
1066 if (NT_STATUS_IS_ERR(result)) {
1067 return result;
1068 }
1069 names = TALLOC_ZERO_P(mem_ctx, struct lsa_TransNameArray);
1070 if (names == NULL) {
1071 return NT_STATUS_NO_MEMORY;
1072 }
1073 names->count = lsa_names2.count;
1074 names->names = talloc_array(names, struct lsa_TranslatedName,
1075 names->count);
1076 if (names->names == NULL) {
1077 return NT_STATUS_NO_MEMORY;
1078 }
1079 for (i=0; i<names->count; i++) {
1080 names->names[i].sid_type = lsa_names2.names[i].sid_type;
1081 names->names[i].name.string = talloc_move(
1082 names->names, &lsa_names2.names[i].name.string);
1083 names->names[i].sid_index = lsa_names2.names[i].sid_index;
1084 }
1085 *pnames = names;
1086 return result;
1087}
1088
1089NTSTATUS rpc_lookup_sids(TALLOC_CTX *mem_ctx,
1090 struct winbindd_domain *domain,
1091 struct lsa_SidArray *sids,
1092 struct lsa_RefDomainList **pdomains,
1093 struct lsa_TransNameArray **pnames)
1094{
1095 struct lsa_TransNameArray *names;
1096 struct rpc_pipe_client *cli = NULL;
1097 struct policy_handle lsa_policy;
1098 uint32_t count;
1099 NTSTATUS status, result;
1100
1101 if (domain->can_do_ncacn_ip_tcp) {
1102 status = rpc_try_lookup_sids3(mem_ctx, domain, sids,
1103 pdomains, pnames);
1104 if (!NT_STATUS_IS_ERR(status)) {
1105 return status;
1106 }
1107 }
1108
1109 status = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
1110 if (!NT_STATUS_IS_OK(status)) {
1111 return status;
1112 }
1113
1114 names = TALLOC_ZERO_P(mem_ctx, struct lsa_TransNameArray);
1115 if (names == NULL) {
1116 return NT_STATUS_NO_MEMORY;
1117 }
1118 status = dcerpc_lsa_LookupSids(cli->binding_handle, mem_ctx,
1119 &lsa_policy, sids, pdomains,
1120 names, LSA_LOOKUP_NAMES_ALL,
1121 &count, &result);
1122 if (!NT_STATUS_IS_OK(status)) {
1123 return status;
1124 }
1125 if (NT_STATUS_IS_ERR(result)) {
1126 return result;
1127 }
1128 *pnames = names;
1129 return result;
1130}
Note: See TracBrowser for help on using the repository browser.