s3-winbindd: add and use winbindd_lookup_sids().
[samba.git] / source3 / winbindd / winbindd_rpc.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    Winbind rpc backend functions
5
6    Copyright (C) Tim Potter 2000-2001,2003
7    Copyright (C) Andrew Tridgell 2001
8    Copyright (C) Volker Lendecke 2005
9    Copyright (C) Guenther Deschner 2008 (pidl conversion)
10    
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 3 of the License, or
14    (at your option) any later version.
15    
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20    
21    You should have received a copy of the GNU General Public License
22    along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 */
24
25 #include "includes.h"
26 #include "winbindd.h"
27
28 #undef DBGC_CLASS
29 #define DBGC_CLASS DBGC_WINBIND
30
31
32 /* Query display info for a domain.  This returns enough information plus a
33    bit extra to give an overview of domain users for the User Manager
34    application. */
35 static NTSTATUS query_user_list(struct winbindd_domain *domain,
36                                TALLOC_CTX *mem_ctx,
37                                uint32 *num_entries, 
38                                WINBIND_USERINFO **info)
39 {
40         NTSTATUS result;
41         struct policy_handle dom_pol;
42         unsigned int i, start_idx;
43         uint32 loop_count;
44         struct rpc_pipe_client *cli;
45
46         DEBUG(3,("rpc: query_user_list\n"));
47
48         *num_entries = 0;
49         *info = NULL;
50
51         if ( !winbindd_can_contact_domain( domain ) ) {
52                 DEBUG(10,("query_user_list: No incoming trust for domain %s\n",
53                           domain->name));
54                 return NT_STATUS_OK;
55         }
56
57         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
58         if (!NT_STATUS_IS_OK(result))
59                 return result;
60
61         i = start_idx = 0;
62         loop_count = 0;
63
64         do {
65                 uint32 num_dom_users, j;
66                 uint32 max_entries, max_size;
67                 uint32_t total_size, returned_size;
68
69                 union samr_DispInfo disp_info;
70
71                 /* this next bit is copied from net_user_list_internal() */
72
73                 get_query_dispinfo_params(loop_count, &max_entries,
74                                           &max_size);
75
76                 result = rpccli_samr_QueryDisplayInfo(cli, mem_ctx,
77                                                       &dom_pol,
78                                                       1,
79                                                       start_idx,
80                                                       max_entries,
81                                                       max_size,
82                                                       &total_size,
83                                                       &returned_size,
84                                                       &disp_info);
85                 num_dom_users = disp_info.info1.count;
86                 start_idx += disp_info.info1.count;
87                 loop_count++;
88
89                 *num_entries += num_dom_users;
90
91                 *info = TALLOC_REALLOC_ARRAY(mem_ctx, *info, WINBIND_USERINFO,
92                                              *num_entries);
93
94                 if (!(*info)) {
95                         return NT_STATUS_NO_MEMORY;
96                 }
97
98                 for (j = 0; j < num_dom_users; i++, j++) {
99
100                         uint32_t rid = disp_info.info1.entries[j].rid;
101
102                         (*info)[i].acct_name = talloc_strdup(mem_ctx,
103                                 disp_info.info1.entries[j].account_name.string);
104                         (*info)[i].full_name = talloc_strdup(mem_ctx,
105                                 disp_info.info1.entries[j].full_name.string);
106                         (*info)[i].homedir = NULL;
107                         (*info)[i].shell = NULL;
108                         sid_compose(&(*info)[i].user_sid, &domain->sid, rid);
109                         
110                         /* For the moment we set the primary group for
111                            every user to be the Domain Users group.
112                            There are serious problems with determining
113                            the actual primary group for large domains.
114                            This should really be made into a 'winbind
115                            force group' smb.conf parameter or
116                            something like that. */
117                            
118                         sid_compose(&(*info)[i].group_sid, &domain->sid, 
119                                     DOMAIN_GROUP_RID_USERS);
120                 }
121
122         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
123
124         return result;
125 }
126
127 /* list all domain groups */
128 static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
129                                 TALLOC_CTX *mem_ctx,
130                                 uint32 *num_entries, 
131                                 struct acct_info **info)
132 {
133         struct policy_handle dom_pol;
134         NTSTATUS status;
135         uint32 start = 0;
136         struct rpc_pipe_client *cli;
137
138         *num_entries = 0;
139         *info = NULL;
140
141         DEBUG(3,("rpc: enum_dom_groups\n"));
142
143         if ( !winbindd_can_contact_domain( domain ) ) {
144                 DEBUG(10,("enum_domain_groups: No incoming trust for domain %s\n",
145                           domain->name));
146                 return NT_STATUS_OK;
147         }
148
149         status = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
150         if (!NT_STATUS_IS_OK(status))
151                 return status;
152
153         do {
154                 struct samr_SamArray *sam_array = NULL;
155                 uint32 count = 0;
156                 TALLOC_CTX *mem_ctx2;
157                 int g;
158
159                 mem_ctx2 = talloc_init("enum_dom_groups[rpc]");
160
161                 /* start is updated by this call. */
162                 status = rpccli_samr_EnumDomainGroups(cli, mem_ctx2,
163                                                       &dom_pol,
164                                                       &start,
165                                                       &sam_array,
166                                                       0xFFFF, /* buffer size? */
167                                                       &count);
168
169                 if (!NT_STATUS_IS_OK(status) &&
170                     !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
171                         talloc_destroy(mem_ctx2);
172                         break;
173                 }
174
175                 (*info) = TALLOC_REALLOC_ARRAY(mem_ctx, *info,
176                                                struct acct_info,
177                                                (*num_entries) + count);
178                 if (! *info) {
179                         talloc_destroy(mem_ctx2);
180                         return NT_STATUS_NO_MEMORY;
181                 }
182
183                 for (g=0; g < count; g++) {
184
185                         fstrcpy((*info)[*num_entries + g].acct_name,
186                                 sam_array->entries[g].name.string);
187                         (*info)[*num_entries + g].rid = sam_array->entries[g].idx;
188                 }
189
190                 (*num_entries) += count;
191                 talloc_destroy(mem_ctx2);
192         } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
193
194         return NT_STATUS_OK;
195 }
196
197 /* List all domain groups */
198
199 static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
200                                 TALLOC_CTX *mem_ctx,
201                                 uint32 *num_entries, 
202                                 struct acct_info **info)
203 {
204         struct policy_handle dom_pol;
205         NTSTATUS result;
206         struct rpc_pipe_client *cli;
207
208         *num_entries = 0;
209         *info = NULL;
210
211         DEBUG(3,("rpc: enum_local_groups\n"));
212
213         if ( !winbindd_can_contact_domain( domain ) ) {
214                 DEBUG(10,("enum_local_groups: No incoming trust for domain %s\n",
215                           domain->name));
216                 return NT_STATUS_OK;
217         }
218
219         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
220         if (!NT_STATUS_IS_OK(result))
221                 return result;
222
223         do {
224                 struct samr_SamArray *sam_array = NULL;
225                 uint32 count = 0, start = *num_entries;
226                 TALLOC_CTX *mem_ctx2;
227                 int g;
228
229                 mem_ctx2 = talloc_init("enum_dom_local_groups[rpc]");
230
231                 result = rpccli_samr_EnumDomainAliases(cli, mem_ctx2,
232                                                        &dom_pol,
233                                                        &start,
234                                                        &sam_array,
235                                                        0xFFFF, /* buffer size? */
236                                                        &count);
237                 if (!NT_STATUS_IS_OK(result) &&
238                     !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES) )
239                 {
240                         talloc_destroy(mem_ctx2);
241                         return result;
242                 }
243
244                 (*info) = TALLOC_REALLOC_ARRAY(mem_ctx, *info,
245                                                struct acct_info,
246                                                (*num_entries) + count);
247                 if (! *info) {
248                         talloc_destroy(mem_ctx2);
249                         return NT_STATUS_NO_MEMORY;
250                 }
251
252                 for (g=0; g < count; g++) {
253
254                         fstrcpy((*info)[*num_entries + g].acct_name,
255                                 sam_array->entries[g].name.string);
256                         (*info)[*num_entries + g].rid = sam_array->entries[g].idx;
257                 }
258
259                 (*num_entries) += count;
260                 talloc_destroy(mem_ctx2);
261
262         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
263
264         return NT_STATUS_OK;
265 }
266
267 /* convert a single name to a sid in a domain */
268 static NTSTATUS msrpc_name_to_sid(struct winbindd_domain *domain,
269                                   TALLOC_CTX *mem_ctx,
270                                   enum winbindd_cmd original_cmd,
271                                   const char *domain_name,
272                                   const char *name,
273                                   DOM_SID *sid,
274                                   enum lsa_SidType *type)
275 {
276         NTSTATUS result;
277         DOM_SID *sids = NULL;
278         enum lsa_SidType *types = NULL;
279         char *full_name = NULL;
280         struct rpc_pipe_client *cli;
281         struct policy_handle lsa_policy;
282         NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL;
283         char *mapped_name = NULL;
284         unsigned int orig_timeout;
285
286         if (name == NULL || *name=='\0') {
287                 full_name = talloc_asprintf(mem_ctx, "%s", domain_name);
288         } else if (domain_name == NULL || *domain_name == '\0') {
289                 full_name = talloc_asprintf(mem_ctx, "%s", name);
290         } else {
291                 full_name = talloc_asprintf(mem_ctx, "%s\\%s", domain_name, name);
292         }
293         if (!full_name) {
294                 DEBUG(0, ("talloc_asprintf failed!\n"));
295                 return NT_STATUS_NO_MEMORY;
296         }
297
298         DEBUG(3,("rpc: name_to_sid name=%s\n", full_name));
299
300         name_map_status = normalize_name_unmap(mem_ctx, full_name,
301                                                &mapped_name);
302
303         /* Reset the full_name pointer if we mapped anytthing */
304
305         if (NT_STATUS_IS_OK(name_map_status) ||
306             NT_STATUS_EQUAL(name_map_status, NT_STATUS_FILE_RENAMED))
307         {
308                 full_name = mapped_name;
309         }
310
311         DEBUG(3,("name_to_sid [rpc] %s for domain %s\n",
312                  full_name?full_name:"", domain_name ));
313
314         result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
315         if (!NT_STATUS_IS_OK(result))
316                 return result;
317
318         /*
319          * This call can take a long time
320          * allow the server to time out.
321          * 35 seconds should do it.
322          */
323         orig_timeout = rpccli_set_timeout(cli, 35000);
324
325         result = rpccli_lsa_lookup_names(cli, mem_ctx, &lsa_policy, 1, 
326                                          (const char**) &full_name, NULL, 1, &sids, &types);
327
328         /* And restore our original timeout. */
329         rpccli_set_timeout(cli, orig_timeout);
330
331         if (!NT_STATUS_IS_OK(result))
332                 return result;
333
334         /* Return rid and type if lookup successful */
335
336         sid_copy(sid, &sids[0]);
337         *type = types[0];
338
339         return NT_STATUS_OK;
340 }
341
342 /*
343   convert a domain SID to a user or group name
344 */
345 static NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain,
346                                   TALLOC_CTX *mem_ctx,
347                                   const DOM_SID *sid,
348                                   char **domain_name,
349                                   char **name,
350                                   enum lsa_SidType *type)
351 {
352         char **domains;
353         char **names;
354         enum lsa_SidType *types = NULL;
355         NTSTATUS result;
356         NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL;
357         char *mapped_name = NULL;
358
359         DEBUG(3,("sid_to_name [rpc] %s for domain %s\n", sid_string_dbg(sid),
360                  domain->name ));
361
362         result = winbindd_lookup_sids(mem_ctx,
363                                       domain,
364                                       1,
365                                       sid,
366                                       &domains,
367                                       &names,
368                                       &types);
369         if (!NT_STATUS_IS_OK(result)) {
370                 DEBUG(2,("msrpc_sid_to_name: failed to lookup sids: %s\n",
371                         nt_errstr(result)));
372                 return result;
373         }
374         
375
376         *type = (enum lsa_SidType)types[0];
377         *domain_name = domains[0];
378         *name = names[0];
379
380         DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name));
381
382         name_map_status = normalize_name_map(mem_ctx, domain, *name,
383                                              &mapped_name);
384         if (NT_STATUS_IS_OK(name_map_status) ||
385             NT_STATUS_EQUAL(name_map_status, NT_STATUS_FILE_RENAMED))
386         {
387                 *name = mapped_name;
388                 DEBUG(5,("returning mapped name -- %s\n", *name));
389         }
390
391         return NT_STATUS_OK;
392 }
393
394 static NTSTATUS msrpc_rids_to_names(struct winbindd_domain *domain,
395                                     TALLOC_CTX *mem_ctx,
396                                     const DOM_SID *sid,
397                                     uint32 *rids,
398                                     size_t num_rids,
399                                     char **domain_name,
400                                     char ***names,
401                                     enum lsa_SidType **types)
402 {
403         char **domains;
404         NTSTATUS result;
405         DOM_SID *sids;
406         size_t i;
407         char **ret_names;
408
409         DEBUG(3, ("rids_to_names [rpc] for domain %s\n", domain->name ));
410
411         if (num_rids) {
412                 sids = TALLOC_ARRAY(mem_ctx, DOM_SID, num_rids);
413                 if (sids == NULL) {
414                         return NT_STATUS_NO_MEMORY;
415                 }
416         } else {
417                 sids = NULL;
418         }
419
420         for (i=0; i<num_rids; i++) {
421                 if (!sid_compose(&sids[i], sid, rids[i])) {
422                         return NT_STATUS_INTERNAL_ERROR;
423                 }
424         }
425
426         result = winbindd_lookup_sids(mem_ctx,
427                                       domain,
428                                       num_rids,
429                                       sids,
430                                       &domains,
431                                       names,
432                                       types);
433
434         if (!NT_STATUS_IS_OK(result) &&
435             !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
436                 return result;
437         }
438
439         ret_names = *names;
440         for (i=0; i<num_rids; i++) {
441                 NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL;
442                 char *mapped_name = NULL;
443
444                 if ((*types)[i] != SID_NAME_UNKNOWN) {
445                         name_map_status = normalize_name_map(mem_ctx,
446                                                              domain,
447                                                              ret_names[i],
448                                                              &mapped_name);
449                         if (NT_STATUS_IS_OK(name_map_status) ||
450                             NT_STATUS_EQUAL(name_map_status, NT_STATUS_FILE_RENAMED))
451                         {
452                                 ret_names[i] = mapped_name;
453                         }
454
455                         *domain_name = domains[i];
456                 }
457         }
458
459         return result;
460 }
461
462 /* Lookup user information from a rid or username. */
463 static NTSTATUS query_user(struct winbindd_domain *domain, 
464                            TALLOC_CTX *mem_ctx, 
465                            const DOM_SID *user_sid, 
466                            WINBIND_USERINFO *user_info)
467 {
468         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
469         struct policy_handle dom_pol, user_pol;
470         union samr_UserInfo *info = NULL;
471         uint32 user_rid;
472         struct netr_SamInfo3 *user;
473         struct rpc_pipe_client *cli;
474
475         DEBUG(3,("rpc: query_user sid=%s\n", sid_string_dbg(user_sid)));
476
477         if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
478                 return NT_STATUS_UNSUCCESSFUL;
479         
480         user_info->homedir = NULL;
481         user_info->shell = NULL;
482         user_info->primary_gid = (gid_t)-1;
483                                                 
484         /* try netsamlogon cache first */
485                         
486         if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL ) 
487         {
488                                 
489                 DEBUG(5,("query_user: Cache lookup succeeded for %s\n", 
490                         sid_string_dbg(user_sid)));
491
492                 sid_compose(&user_info->user_sid, &domain->sid, user->base.rid);
493                 sid_compose(&user_info->group_sid, &domain->sid,
494                             user->base.primary_gid);
495                                 
496                 user_info->acct_name = talloc_strdup(mem_ctx,
497                                                      user->base.account_name.string);
498                 user_info->full_name = talloc_strdup(mem_ctx,
499                                                      user->base.full_name.string);
500                 
501                 TALLOC_FREE(user);
502                                                 
503                 return NT_STATUS_OK;
504         }
505                                 
506         if ( !winbindd_can_contact_domain( domain ) ) {
507                 DEBUG(10,("query_user: No incoming trust for domain %s\n",
508                           domain->name));
509                 return NT_STATUS_OK;
510         }
511         
512         if ( !winbindd_can_contact_domain( domain ) ) {
513                 DEBUG(10,("query_user: No incoming trust for domain %s\n",
514                           domain->name));
515                 return NT_STATUS_OK;
516         }
517         
518         if ( !winbindd_can_contact_domain( domain ) ) {
519                 DEBUG(10,("query_user: No incoming trust for domain %s\n",
520                           domain->name));
521                 return NT_STATUS_OK;
522         }
523         
524         /* no cache; hit the wire */
525                 
526         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
527         if (!NT_STATUS_IS_OK(result))
528                 return result;
529
530         /* Get user handle */
531         result = rpccli_samr_OpenUser(cli, mem_ctx,
532                                       &dom_pol,
533                                       SEC_FLAG_MAXIMUM_ALLOWED,
534                                       user_rid,
535                                       &user_pol);
536
537         if (!NT_STATUS_IS_OK(result))
538                 return result;
539
540         /* Get user info */
541         result = rpccli_samr_QueryUserInfo(cli, mem_ctx,
542                                            &user_pol,
543                                            0x15,
544                                            &info);
545
546         rpccli_samr_Close(cli, mem_ctx, &user_pol);
547
548         if (!NT_STATUS_IS_OK(result))
549                 return result;
550
551         sid_compose(&user_info->user_sid, &domain->sid, user_rid);
552         sid_compose(&user_info->group_sid, &domain->sid,
553                     info->info21.primary_gid);
554         user_info->acct_name = talloc_strdup(mem_ctx,
555                                              info->info21.account_name.string);
556         user_info->full_name = talloc_strdup(mem_ctx,
557                                              info->info21.full_name.string);
558         user_info->homedir = NULL;
559         user_info->shell = NULL;
560         user_info->primary_gid = (gid_t)-1;
561
562         return NT_STATUS_OK;
563 }                                   
564
565 /* Lookup groups a user is a member of.  I wish Unix had a call like this! */
566 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
567                                   TALLOC_CTX *mem_ctx,
568                                   const DOM_SID *user_sid,
569                                   uint32 *num_groups, DOM_SID **user_grpsids)
570 {
571         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
572         struct policy_handle dom_pol, user_pol;
573         uint32 des_access = SEC_FLAG_MAXIMUM_ALLOWED;
574         struct samr_RidWithAttributeArray *rid_array = NULL;
575         unsigned int i;
576         uint32 user_rid;
577         struct rpc_pipe_client *cli;
578
579         DEBUG(3,("rpc: lookup_usergroups sid=%s\n", sid_string_dbg(user_sid)));
580
581         if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
582                 return NT_STATUS_UNSUCCESSFUL;
583
584         *num_groups = 0;
585         *user_grpsids = NULL;
586
587         /* so lets see if we have a cached user_info_3 */
588         result = lookup_usergroups_cached(domain, mem_ctx, user_sid, 
589                                           num_groups, user_grpsids);
590
591         if (NT_STATUS_IS_OK(result)) {
592                 return NT_STATUS_OK;
593         }
594
595         if ( !winbindd_can_contact_domain( domain ) ) {
596                 DEBUG(10,("lookup_usergroups: No incoming trust for domain %s\n",
597                           domain->name));
598
599                 /* Tell the cache manager not to remember this one */
600
601                 return NT_STATUS_SYNCHRONIZATION_REQUIRED;
602         }
603
604         /* no cache; hit the wire */
605         
606         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
607         if (!NT_STATUS_IS_OK(result))
608                 return result;
609
610         /* Get user handle */
611         result = rpccli_samr_OpenUser(cli, mem_ctx,
612                                       &dom_pol,
613                                       des_access,
614                                       user_rid,
615                                       &user_pol);
616
617         if (!NT_STATUS_IS_OK(result))
618                 return result;
619
620         /* Query user rids */
621         result = rpccli_samr_GetGroupsForUser(cli, mem_ctx,
622                                               &user_pol,
623                                               &rid_array);
624         *num_groups = rid_array->count;
625
626         rpccli_samr_Close(cli, mem_ctx, &user_pol);
627
628         if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0)
629                 return result;
630
631         (*user_grpsids) = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_groups);
632         if (!(*user_grpsids))
633                 return NT_STATUS_NO_MEMORY;
634
635         for (i=0;i<(*num_groups);i++) {
636                 sid_copy(&((*user_grpsids)[i]), &domain->sid);
637                 sid_append_rid(&((*user_grpsids)[i]),
638                                 rid_array->rids[i].rid);
639         }
640
641         return NT_STATUS_OK;
642 }
643
644 #define MAX_SAM_ENTRIES_W2K 0x400 /* 1024 */
645
646 static NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain,
647                                          TALLOC_CTX *mem_ctx,
648                                          uint32 num_sids, const DOM_SID *sids,
649                                          uint32 *num_aliases,
650                                          uint32 **alias_rids)
651 {
652         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
653         struct policy_handle dom_pol;
654         uint32 num_query_sids = 0;
655         int i;
656         struct rpc_pipe_client *cli;
657         struct samr_Ids alias_rids_query;
658         int rangesize = MAX_SAM_ENTRIES_W2K;
659         uint32 total_sids = 0;
660         int num_queries = 1;
661
662         *num_aliases = 0;
663         *alias_rids = NULL;
664
665         DEBUG(3,("rpc: lookup_useraliases\n"));
666
667         if ( !winbindd_can_contact_domain( domain ) ) {
668                 DEBUG(10,("msrpc_lookup_useraliases: No incoming trust for domain %s\n",
669                           domain->name));
670                 return NT_STATUS_OK;
671         }
672
673         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
674         if (!NT_STATUS_IS_OK(result))
675                 return result;
676
677         do {
678                 /* prepare query */
679                 struct lsa_SidArray sid_array;
680
681                 ZERO_STRUCT(sid_array);
682
683                 num_query_sids = MIN(num_sids - total_sids, rangesize);
684
685                 DEBUG(10,("rpc: lookup_useraliases: entering query %d for %d sids\n", 
686                         num_queries, num_query_sids));  
687
688                 if (num_query_sids) {
689                         sid_array.sids = TALLOC_ZERO_ARRAY(mem_ctx, struct lsa_SidPtr, num_query_sids);
690                         if (sid_array.sids == NULL) {
691                                 return NT_STATUS_NO_MEMORY;
692                         }
693                 } else {
694                         sid_array.sids = NULL;
695                 }
696
697                 for (i=0; i<num_query_sids; i++) {
698                         sid_array.sids[i].sid = sid_dup_talloc(mem_ctx, &sids[total_sids++]);
699                         if (!sid_array.sids[i].sid) {
700                                 TALLOC_FREE(sid_array.sids);
701                                 return NT_STATUS_NO_MEMORY;
702                         }
703                 }
704                 sid_array.num_sids = num_query_sids;
705
706                 /* do request */
707                 result = rpccli_samr_GetAliasMembership(cli, mem_ctx,
708                                                         &dom_pol,
709                                                         &sid_array,
710                                                         &alias_rids_query);
711
712                 if (!NT_STATUS_IS_OK(result)) {
713                         *num_aliases = 0;
714                         *alias_rids = NULL;
715                         TALLOC_FREE(sid_array.sids);
716                         goto done;
717                 }
718
719                 /* process output */
720
721                 for (i=0; i<alias_rids_query.count; i++) {
722                         size_t na = *num_aliases;
723                         if (!add_rid_to_array_unique(mem_ctx, alias_rids_query.ids[i],
724                                                 alias_rids, &na)) {
725                                 return NT_STATUS_NO_MEMORY;
726                         }
727                         *num_aliases = na;
728                 }
729
730                 TALLOC_FREE(sid_array.sids);
731
732                 num_queries++;
733
734         } while (total_sids < num_sids);
735
736  done:
737         DEBUG(10,("rpc: lookup_useraliases: got %d aliases in %d queries "
738                 "(rangesize: %d)\n", *num_aliases, num_queries, rangesize));
739
740         return result;
741 }
742
743
744 /* Lookup group membership given a rid.   */
745 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
746                                 TALLOC_CTX *mem_ctx,
747                                 const DOM_SID *group_sid, uint32 *num_names, 
748                                 DOM_SID **sid_mem, char ***names, 
749                                 uint32 **name_types)
750 {
751         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
752         uint32 i, total_names = 0;
753         struct policy_handle dom_pol, group_pol;
754         uint32 des_access = SEC_FLAG_MAXIMUM_ALLOWED;
755         uint32 *rid_mem = NULL;
756         uint32 group_rid;
757         unsigned int j, r;
758         struct rpc_pipe_client *cli;
759         unsigned int orig_timeout;
760         struct samr_RidTypeArray *rids = NULL;
761
762         DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain->name,
763                   sid_string_dbg(group_sid)));
764
765         if ( !winbindd_can_contact_domain( domain ) ) {
766                 DEBUG(10,("lookup_groupmem: No incoming trust for domain %s\n",
767                           domain->name));
768                 return NT_STATUS_OK;
769         }
770
771         if (!sid_peek_check_rid(&domain->sid, group_sid, &group_rid))
772                 return NT_STATUS_UNSUCCESSFUL;
773
774         *num_names = 0;
775
776         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
777         if (!NT_STATUS_IS_OK(result))
778                 return result;
779
780         result = rpccli_samr_OpenGroup(cli, mem_ctx,
781                                        &dom_pol,
782                                        des_access,
783                                        group_rid,
784                                        &group_pol);
785
786         if (!NT_STATUS_IS_OK(result))
787                 return result;
788
789         /* Step #1: Get a list of user rids that are the members of the
790            group. */
791
792         /* This call can take a long time - allow the server to time out.
793            35 seconds should do it. */
794
795         orig_timeout = rpccli_set_timeout(cli, 35000);
796
797         result = rpccli_samr_QueryGroupMember(cli, mem_ctx,
798                                               &group_pol,
799                                               &rids);
800
801         /* And restore our original timeout. */
802         rpccli_set_timeout(cli, orig_timeout);
803
804         rpccli_samr_Close(cli, mem_ctx, &group_pol);
805
806         if (!NT_STATUS_IS_OK(result))
807                 return result;
808
809         *num_names = rids->count;
810         rid_mem = rids->rids;
811
812         if (!*num_names) {
813                 names = NULL;
814                 name_types = NULL;
815                 sid_mem = NULL;
816                 return NT_STATUS_OK;
817         }
818
819         /* Step #2: Convert list of rids into list of usernames.  Do this
820            in bunches of ~1000 to avoid crashing NT4.  It looks like there
821            is a buffer overflow or something like that lurking around
822            somewhere. */
823
824 #define MAX_LOOKUP_RIDS 900
825
826         *names = TALLOC_ZERO_ARRAY(mem_ctx, char *, *num_names);
827         *name_types = TALLOC_ZERO_ARRAY(mem_ctx, uint32, *num_names);
828         *sid_mem = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, *num_names);
829
830         for (j=0;j<(*num_names);j++)
831                 sid_compose(&(*sid_mem)[j], &domain->sid, rid_mem[j]);
832         
833         if (*num_names>0 && (!*names || !*name_types))
834                 return NT_STATUS_NO_MEMORY;
835
836         for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) {
837                 int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS);
838                 struct lsa_Strings tmp_names;
839                 struct samr_Ids tmp_types;
840
841                 /* Lookup a chunk of rids */
842
843                 result = rpccli_samr_LookupRids(cli, mem_ctx,
844                                                 &dom_pol,
845                                                 num_lookup_rids,
846                                                 &rid_mem[i],
847                                                 &tmp_names,
848                                                 &tmp_types);
849
850                 /* see if we have a real error (and yes the
851                    STATUS_SOME_UNMAPPED is the one returned from 2k) */
852
853                 if (!NT_STATUS_IS_OK(result) &&
854                     !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
855                         return result;
856
857                 /* Copy result into array.  The talloc system will take
858                    care of freeing the temporary arrays later on. */
859
860                 if (tmp_names.count != tmp_types.count) {
861                         return NT_STATUS_UNSUCCESSFUL;
862                 }
863
864                 for (r=0; r<tmp_names.count; r++) {
865                         if (tmp_types.ids[r] == SID_NAME_UNKNOWN) {
866                                 continue;
867                         }
868                         (*names)[total_names] = fill_domain_username_talloc(
869                                 mem_ctx, domain->name,
870                                 tmp_names.names[r].string, true);
871                         (*name_types)[total_names] = tmp_types.ids[r];
872                         total_names += 1;
873                 }
874         }
875
876         *num_names = total_names;
877
878         return NT_STATUS_OK;
879 }
880
881 #ifdef HAVE_LDAP
882
883 #include <ldap.h>
884
885 static int get_ldap_seq(const char *server, int port, uint32 *seq)
886 {
887         int ret = -1;
888         struct timeval to;
889         const char *attrs[] = {"highestCommittedUSN", NULL};
890         LDAPMessage *res = NULL;
891         char **values = NULL;
892         LDAP *ldp = NULL;
893
894         *seq = DOM_SEQUENCE_NONE;
895
896         /*
897          * Parameterised (5) second timeout on open. This is needed as the
898          * search timeout doesn't seem to apply to doing an open as well. JRA.
899          */
900
901         ldp = ldap_open_with_timeout(server, port, lp_ldap_timeout());
902         if (ldp == NULL)
903                 return -1;
904
905         /* Timeout if no response within 20 seconds. */
906         to.tv_sec = 10;
907         to.tv_usec = 0;
908
909         if (ldap_search_st(ldp, "", LDAP_SCOPE_BASE, "(objectclass=*)",
910                            CONST_DISCARD(char **, attrs), 0, &to, &res))
911                 goto done;
912
913         if (ldap_count_entries(ldp, res) != 1)
914                 goto done;
915
916         values = ldap_get_values(ldp, res, "highestCommittedUSN");
917         if (!values || !values[0])
918                 goto done;
919
920         *seq = atoi(values[0]);
921         ret = 0;
922
923   done:
924
925         if (values)
926                 ldap_value_free(values);
927         if (res)
928                 ldap_msgfree(res);
929         if (ldp)
930                 ldap_unbind(ldp);
931         return ret;
932 }
933
934 /**********************************************************************
935  Get the sequence number for a Windows AD native mode domain using
936  LDAP queries.
937 **********************************************************************/
938
939 static int get_ldap_sequence_number(struct winbindd_domain *domain, uint32 *seq)
940 {
941         int ret = -1;
942         char addr[INET6_ADDRSTRLEN];
943
944         print_sockaddr(addr, sizeof(addr), &domain->dcaddr);
945         if ((ret = get_ldap_seq(addr, LDAP_PORT, seq)) == 0) {
946                 DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence "
947                           "number for Domain (%s) from DC (%s)\n",
948                         domain->name, addr));
949         }
950         return ret;
951 }
952
953 #endif /* HAVE_LDAP */
954
955 /* find the sequence number for a domain */
956 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
957 {
958         TALLOC_CTX *mem_ctx;
959         union samr_DomainInfo *info = NULL;
960         NTSTATUS result;
961         struct policy_handle dom_pol;
962         bool got_seq_num = False;
963         struct rpc_pipe_client *cli;
964
965         DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name));
966
967         if ( !winbindd_can_contact_domain( domain ) ) {
968                 DEBUG(10,("sequence_number: No incoming trust for domain %s\n",
969                           domain->name));
970                 *seq = time(NULL);
971                 return NT_STATUS_OK;
972         }
973
974         *seq = DOM_SEQUENCE_NONE;
975
976         if (!(mem_ctx = talloc_init("sequence_number[rpc]")))
977                 return NT_STATUS_NO_MEMORY;
978
979 #ifdef HAVE_LDAP
980         if ( domain->active_directory ) 
981         {
982                 int res;
983
984                 DEBUG(8,("using get_ldap_seq() to retrieve the "
985                          "sequence number\n"));
986
987                 res =  get_ldap_sequence_number( domain, seq );
988                 if (res == 0)
989                 {                       
990                         result = NT_STATUS_OK;
991                         DEBUG(10,("domain_sequence_number: LDAP for "
992                                   "domain %s is %u\n",
993                                   domain->name, *seq));
994                         goto done;
995                 }
996
997                 DEBUG(10,("domain_sequence_number: failed to get LDAP "
998                           "sequence number for domain %s\n",
999                           domain->name ));
1000         }
1001 #endif /* HAVE_LDAP */
1002
1003         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
1004         if (!NT_STATUS_IS_OK(result)) {
1005                 goto done;
1006         }
1007
1008         /* Query domain info */
1009
1010         result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
1011                                              &dom_pol,
1012                                              8,
1013                                              &info);
1014
1015         if (NT_STATUS_IS_OK(result)) {
1016                 *seq = info->info8.sequence_num;
1017                 got_seq_num = True;
1018                 goto seq_num;
1019         }
1020
1021         /* retry with info-level 2 in case the dc does not support info-level 8
1022          * (like all older samba2 and samba3 dc's) - Guenther */
1023
1024         result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
1025                                              &dom_pol,
1026                                              2,
1027                                              &info);
1028
1029         if (NT_STATUS_IS_OK(result)) {
1030                 *seq = info->general.sequence_num;
1031                 got_seq_num = True;
1032         }
1033
1034  seq_num:
1035         if (got_seq_num) {
1036                 DEBUG(10,("domain_sequence_number: for domain %s is %u\n",
1037                           domain->name, (unsigned)*seq));
1038         } else {
1039                 DEBUG(10,("domain_sequence_number: failed to get sequence "
1040                           "number (%u) for domain %s\n",
1041                           (unsigned)*seq, domain->name ));
1042         }
1043
1044   done:
1045
1046         talloc_destroy(mem_ctx);
1047
1048         return result;
1049 }
1050
1051 /* get a list of trusted domains */
1052 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
1053                                 TALLOC_CTX *mem_ctx,
1054                                 uint32 *num_domains,
1055                                 char ***names,
1056                                 char ***alt_names,
1057                                 DOM_SID **dom_sids)
1058 {
1059         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1060         uint32 enum_ctx = 0;
1061         struct rpc_pipe_client *cli;
1062         struct policy_handle lsa_policy;
1063
1064         DEBUG(3,("rpc: trusted_domains\n"));
1065
1066         *num_domains = 0;
1067         *names = NULL;
1068         *alt_names = NULL;
1069         *dom_sids = NULL;
1070
1071         result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
1072         if (!NT_STATUS_IS_OK(result))
1073                 return result;
1074
1075         result = STATUS_MORE_ENTRIES;
1076
1077         while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
1078                 uint32 start_idx;
1079                 int i;
1080                 struct lsa_DomainList dom_list;
1081
1082                 result = rpccli_lsa_EnumTrustDom(cli, mem_ctx,
1083                                                  &lsa_policy,
1084                                                  &enum_ctx,
1085                                                  &dom_list,
1086                                                  (uint32_t)-1);
1087
1088                 if (!NT_STATUS_IS_OK(result) &&
1089                     !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
1090                         break;
1091
1092                 start_idx = *num_domains;
1093                 *num_domains += dom_list.count;
1094                 *names = TALLOC_REALLOC_ARRAY(mem_ctx, *names,
1095                                               char *, *num_domains);
1096                 *dom_sids = TALLOC_REALLOC_ARRAY(mem_ctx, *dom_sids,
1097                                                  DOM_SID, *num_domains);
1098                 *alt_names = TALLOC_REALLOC_ARRAY(mem_ctx, *alt_names,
1099                                                  char *, *num_domains);
1100                 if ((*names == NULL) || (*dom_sids == NULL) ||
1101                     (*alt_names == NULL))
1102                         return NT_STATUS_NO_MEMORY;
1103
1104                 for (i=0; i<dom_list.count; i++) {
1105                         (*names)[start_idx+i] = CONST_DISCARD(char *, dom_list.domains[i].name.string);
1106                         (*dom_sids)[start_idx+i] = *dom_list.domains[i].sid;
1107                         (*alt_names)[start_idx+i] = talloc_strdup(mem_ctx, "");
1108                 }
1109         }
1110         return result;
1111 }
1112
1113 /* find the lockout policy for a domain */
1114 static NTSTATUS msrpc_lockout_policy(struct winbindd_domain *domain,
1115                                      TALLOC_CTX *mem_ctx,
1116                                      struct samr_DomInfo12 *lockout_policy)
1117 {
1118         NTSTATUS result;
1119         struct rpc_pipe_client *cli;
1120         struct policy_handle dom_pol;
1121         union samr_DomainInfo *info = NULL;
1122
1123         DEBUG(10,("rpc: fetch lockout policy for %s\n", domain->name));
1124
1125         if ( !winbindd_can_contact_domain( domain ) ) {
1126                 DEBUG(10,("msrpc_lockout_policy: No incoming trust for domain %s\n",
1127                           domain->name));
1128                 return NT_STATUS_NOT_SUPPORTED;
1129         }
1130
1131         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
1132         if (!NT_STATUS_IS_OK(result)) {
1133                 goto done;
1134         }
1135
1136         result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
1137                                              &dom_pol,
1138                                              12,
1139                                              &info);
1140         if (!NT_STATUS_IS_OK(result)) {
1141                 goto done;
1142         }
1143
1144         *lockout_policy = info->info12;
1145
1146         DEBUG(10,("msrpc_lockout_policy: lockout_threshold %d\n",
1147                 info->info12.lockout_threshold));
1148
1149   done:
1150
1151         return result;
1152 }
1153
1154 /* find the password policy for a domain */
1155 static NTSTATUS msrpc_password_policy(struct winbindd_domain *domain,
1156                                       TALLOC_CTX *mem_ctx,
1157                                       struct samr_DomInfo1 *password_policy)
1158 {
1159         NTSTATUS result;
1160         struct rpc_pipe_client *cli;
1161         struct policy_handle dom_pol;
1162         union samr_DomainInfo *info = NULL;
1163
1164         DEBUG(10,("rpc: fetch password policy for %s\n", domain->name));
1165
1166         if ( !winbindd_can_contact_domain( domain ) ) {
1167                 DEBUG(10,("msrpc_password_policy: No incoming trust for domain %s\n",
1168                           domain->name));
1169                 return NT_STATUS_NOT_SUPPORTED;
1170         }
1171
1172         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
1173         if (!NT_STATUS_IS_OK(result)) {
1174                 goto done;
1175         }
1176
1177         result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
1178                                              &dom_pol,
1179                                              1,
1180                                              &info);
1181         if (!NT_STATUS_IS_OK(result)) {
1182                 goto done;
1183         }
1184
1185         *password_policy = info->info1;
1186
1187         DEBUG(10,("msrpc_password_policy: min_length_password %d\n",
1188                 info->info1.min_password_length));
1189
1190   done:
1191
1192         return result;
1193 }
1194
1195 NTSTATUS winbindd_lookup_sids(TALLOC_CTX *mem_ctx,
1196                               struct winbindd_domain *domain,
1197                               uint32_t num_sids,
1198                               const struct dom_sid *sids,
1199                               char ***domains,
1200                               char ***names,
1201                               enum lsa_SidType **types)
1202 {
1203         NTSTATUS status;
1204         struct rpc_pipe_client *cli = NULL;
1205         struct policy_handle lsa_policy;
1206         unsigned int orig_timeout;
1207
1208         status = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
1209         if (!NT_STATUS_IS_OK(status)) {
1210                 return status;
1211         }
1212
1213         /*
1214          * This call can take a long time
1215          * allow the server to time out.
1216          * 35 seconds should do it.
1217          */
1218         orig_timeout = rpccli_set_timeout(cli, 35000);
1219
1220         status = rpccli_lsa_lookup_sids(cli, mem_ctx, &lsa_policy,
1221                                         num_sids, sids, domains,
1222                                         names, types);
1223
1224         /* And restore our original timeout. */
1225         rpccli_set_timeout(cli, orig_timeout);
1226
1227         if (!NT_STATUS_IS_OK(status)) {
1228                 return status;
1229         }
1230
1231         return status;
1232 }
1233
1234
1235 /* the rpc backend methods are exposed via this structure */
1236 struct winbindd_methods msrpc_methods = {
1237         False,
1238         query_user_list,
1239         enum_dom_groups,
1240         enum_local_groups,
1241         msrpc_name_to_sid,
1242         msrpc_sid_to_name,
1243         msrpc_rids_to_names,
1244         query_user,
1245         lookup_usergroups,
1246         msrpc_lookup_useraliases,
1247         lookup_groupmem,
1248         sequence_number,
1249         msrpc_lockout_policy,
1250         msrpc_password_policy,
1251         trusted_domains,
1252 };