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