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