df8d7b52c25e21fda75035f838cd2dbd08160d4f
[kai/samba.git] / source3 / winbindd / winbindd_rpc.c
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 */
37 NTSTATUS 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(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 */
145 NTSTATUS 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(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
208 NTSTATUS 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(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 */
268 NTSTATUS 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 */
331 NTSTATUS 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 */
387 NTSTATUS 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. */
466 NTSTATUS 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. */
542 NTSTATUS 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
615 NTSTATUS 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.   */
705 NTSTATUS 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 */
902 NTSTATUS 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
946 seq_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 */
961 NTSTATUS 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
1034 static 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
1089 NTSTATUS 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 }