s3-winbindd: make all winbind rpc-methods static.
[kai/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         POLICY_HND 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         POLICY_HND 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         POLICY_HND 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         POLICY_HND lsa_policy;
282         NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL;
283         char *mapped_name = NULL;
284
285         if (name == NULL || *name=='\0') {
286                 full_name = talloc_asprintf(mem_ctx, "%s", domain_name);
287         } else if (domain_name == NULL || *domain_name == '\0') {
288                 full_name = talloc_asprintf(mem_ctx, "%s", name);
289         } else {
290                 full_name = talloc_asprintf(mem_ctx, "%s\\%s", domain_name, name);
291         }
292         if (!full_name) {
293                 DEBUG(0, ("talloc_asprintf failed!\n"));
294                 return NT_STATUS_NO_MEMORY;
295         }
296
297         DEBUG(3,("rpc: name_to_sid name=%s\n", full_name));
298
299         name_map_status = normalize_name_unmap(mem_ctx, full_name,
300                                                &mapped_name);
301
302         /* Reset the full_name pointer if we mapped anytthing */
303
304         if (NT_STATUS_IS_OK(name_map_status) ||
305             NT_STATUS_EQUAL(name_map_status, NT_STATUS_FILE_RENAMED))
306         {
307                 full_name = mapped_name;
308         }
309
310         DEBUG(3,("name_to_sid [rpc] %s for domain %s\n",
311                  full_name?full_name:"", domain_name ));
312
313         result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
314         if (!NT_STATUS_IS_OK(result))
315                 return result;
316
317         result = rpccli_lsa_lookup_names(cli, mem_ctx, &lsa_policy, 1, 
318                                          (const char**) &full_name, NULL, 1, &sids, &types);
319         
320         if (!NT_STATUS_IS_OK(result))
321                 return result;
322
323         /* Return rid and type if lookup successful */
324
325         sid_copy(sid, &sids[0]);
326         *type = types[0];
327
328         return NT_STATUS_OK;
329 }
330
331 /*
332   convert a domain SID to a user or group name
333 */
334 static NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain,
335                                   TALLOC_CTX *mem_ctx,
336                                   const DOM_SID *sid,
337                                   char **domain_name,
338                                   char **name,
339                                   enum lsa_SidType *type)
340 {
341         char **domains;
342         char **names;
343         enum lsa_SidType *types = NULL;
344         NTSTATUS result;
345         struct rpc_pipe_client *cli;
346         POLICY_HND lsa_policy;
347         NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL;
348         char *mapped_name = NULL;
349
350         DEBUG(3,("sid_to_name [rpc] %s for domain %s\n", sid_string_dbg(sid),
351                  domain->name ));
352
353         result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
354         if (!NT_STATUS_IS_OK(result)) {
355                 DEBUG(2,("msrpc_sid_to_name: cm_connect_lsa() failed (%s)\n",
356                          nt_errstr(result)));           
357                 return result;
358         }
359         
360
361         result = rpccli_lsa_lookup_sids(cli, mem_ctx, &lsa_policy,
362                                         1, sid, &domains, &names, &types);
363         if (!NT_STATUS_IS_OK(result)) {         
364                 DEBUG(2,("msrpc_sid_to_name: rpccli_lsa_lookup_sids()  failed (%s)\n",
365                          nt_errstr(result)));           
366                 return result;
367         }
368
369         *type = (enum lsa_SidType)types[0];
370         *domain_name = domains[0];
371         *name = names[0];
372
373         DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name));
374
375         name_map_status = normalize_name_map(mem_ctx, domain, *name,
376                                              &mapped_name);
377         if (NT_STATUS_IS_OK(name_map_status) ||
378             NT_STATUS_EQUAL(name_map_status, NT_STATUS_FILE_RENAMED))
379         {
380                 *name = mapped_name;
381                 DEBUG(5,("returning mapped name -- %s\n", *name));
382         }
383
384         return NT_STATUS_OK;
385 }
386
387 static NTSTATUS msrpc_rids_to_names(struct winbindd_domain *domain,
388                                     TALLOC_CTX *mem_ctx,
389                                     const DOM_SID *sid,
390                                     uint32 *rids,
391                                     size_t num_rids,
392                                     char **domain_name,
393                                     char ***names,
394                                     enum lsa_SidType **types)
395 {
396         char **domains;
397         NTSTATUS result;
398         struct rpc_pipe_client *cli;
399         POLICY_HND lsa_policy;
400         DOM_SID *sids;
401         size_t i;
402         char **ret_names;
403
404         DEBUG(3, ("rids_to_names [rpc] for domain %s\n", domain->name ));
405
406         if (num_rids) {
407                 sids = TALLOC_ARRAY(mem_ctx, DOM_SID, num_rids);
408                 if (sids == NULL) {
409                         return NT_STATUS_NO_MEMORY;
410                 }
411         } else {
412                 sids = NULL;
413         }
414
415         for (i=0; i<num_rids; i++) {
416                 if (!sid_compose(&sids[i], sid, rids[i])) {
417                         return NT_STATUS_INTERNAL_ERROR;
418                 }
419         }
420
421         result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
422         if (!NT_STATUS_IS_OK(result)) {
423                 return result;
424         }
425
426         result = rpccli_lsa_lookup_sids(cli, mem_ctx, &lsa_policy,
427                                         num_rids, sids, &domains,
428                                         names, types);
429         if (!NT_STATUS_IS_OK(result) &&
430             !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
431                 return result;
432         }
433
434         ret_names = *names;
435         for (i=0; i<num_rids; i++) {
436                 NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL;
437                 char *mapped_name = NULL;
438
439                 if ((*types)[i] != SID_NAME_UNKNOWN) {
440                         name_map_status = normalize_name_map(mem_ctx,
441                                                              domain,
442                                                              ret_names[i],
443                                                              &mapped_name);
444                         if (NT_STATUS_IS_OK(name_map_status) ||
445                             NT_STATUS_EQUAL(name_map_status, NT_STATUS_FILE_RENAMED))
446                         {
447                                 ret_names[i] = mapped_name;
448                         }
449
450                         *domain_name = domains[i];
451                 }
452         }
453
454         return result;
455 }
456
457 /* Lookup user information from a rid or username. */
458 static NTSTATUS query_user(struct winbindd_domain *domain, 
459                            TALLOC_CTX *mem_ctx, 
460                            const DOM_SID *user_sid, 
461                            WINBIND_USERINFO *user_info)
462 {
463         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
464         POLICY_HND dom_pol, user_pol;
465         union samr_UserInfo *info = NULL;
466         uint32 user_rid;
467         struct netr_SamInfo3 *user;
468         struct rpc_pipe_client *cli;
469
470         DEBUG(3,("rpc: query_user sid=%s\n", sid_string_dbg(user_sid)));
471
472         if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
473                 return NT_STATUS_UNSUCCESSFUL;
474         
475         user_info->homedir = NULL;
476         user_info->shell = NULL;
477         user_info->primary_gid = (gid_t)-1;
478                                                 
479         /* try netsamlogon cache first */
480                         
481         if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL ) 
482         {
483                                 
484                 DEBUG(5,("query_user: Cache lookup succeeded for %s\n", 
485                         sid_string_dbg(user_sid)));
486
487                 sid_compose(&user_info->user_sid, &domain->sid, user->base.rid);
488                 sid_compose(&user_info->group_sid, &domain->sid,
489                             user->base.primary_gid);
490                                 
491                 user_info->acct_name = talloc_strdup(mem_ctx,
492                                                      user->base.account_name.string);
493                 user_info->full_name = talloc_strdup(mem_ctx,
494                                                      user->base.full_name.string);
495                 
496                 TALLOC_FREE(user);
497                                                 
498                 return NT_STATUS_OK;
499         }
500                                 
501         if ( !winbindd_can_contact_domain( domain ) ) {
502                 DEBUG(10,("query_user: No incoming trust for domain %s\n",
503                           domain->name));
504                 return NT_STATUS_OK;
505         }
506         
507         if ( !winbindd_can_contact_domain( domain ) ) {
508                 DEBUG(10,("query_user: No incoming trust for domain %s\n",
509                           domain->name));
510                 return NT_STATUS_OK;
511         }
512         
513         if ( !winbindd_can_contact_domain( domain ) ) {
514                 DEBUG(10,("query_user: No incoming trust for domain %s\n",
515                           domain->name));
516                 return NT_STATUS_OK;
517         }
518         
519         /* no cache; hit the wire */
520                 
521         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
522         if (!NT_STATUS_IS_OK(result))
523                 return result;
524
525         /* Get user handle */
526         result = rpccli_samr_OpenUser(cli, mem_ctx,
527                                       &dom_pol,
528                                       SEC_RIGHTS_MAXIMUM_ALLOWED,
529                                       user_rid,
530                                       &user_pol);
531
532         if (!NT_STATUS_IS_OK(result))
533                 return result;
534
535         /* Get user info */
536         result = rpccli_samr_QueryUserInfo(cli, mem_ctx,
537                                            &user_pol,
538                                            0x15,
539                                            &info);
540
541         rpccli_samr_Close(cli, mem_ctx, &user_pol);
542
543         if (!NT_STATUS_IS_OK(result))
544                 return result;
545
546         sid_compose(&user_info->user_sid, &domain->sid, user_rid);
547         sid_compose(&user_info->group_sid, &domain->sid,
548                     info->info21.primary_gid);
549         user_info->acct_name = talloc_strdup(mem_ctx,
550                                              info->info21.account_name.string);
551         user_info->full_name = talloc_strdup(mem_ctx,
552                                              info->info21.full_name.string);
553         user_info->homedir = NULL;
554         user_info->shell = NULL;
555         user_info->primary_gid = (gid_t)-1;
556
557         return NT_STATUS_OK;
558 }                                   
559
560 /* Lookup groups a user is a member of.  I wish Unix had a call like this! */
561 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
562                                   TALLOC_CTX *mem_ctx,
563                                   const DOM_SID *user_sid,
564                                   uint32 *num_groups, DOM_SID **user_grpsids)
565 {
566         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
567         POLICY_HND dom_pol, user_pol;
568         uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
569         struct samr_RidWithAttributeArray *rid_array = NULL;
570         unsigned int i;
571         uint32 user_rid;
572         struct rpc_pipe_client *cli;
573
574         DEBUG(3,("rpc: lookup_usergroups sid=%s\n", sid_string_dbg(user_sid)));
575
576         if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
577                 return NT_STATUS_UNSUCCESSFUL;
578
579         *num_groups = 0;
580         *user_grpsids = NULL;
581
582         /* so lets see if we have a cached user_info_3 */
583         result = lookup_usergroups_cached(domain, mem_ctx, user_sid, 
584                                           num_groups, user_grpsids);
585
586         if (NT_STATUS_IS_OK(result)) {
587                 return NT_STATUS_OK;
588         }
589
590         if ( !winbindd_can_contact_domain( domain ) ) {
591                 DEBUG(10,("lookup_usergroups: No incoming trust for domain %s\n",
592                           domain->name));
593
594                 /* Tell the cache manager not to remember this one */
595
596                 return NT_STATUS_SYNCHRONIZATION_REQUIRED;
597         }
598
599         /* no cache; hit the wire */
600         
601         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
602         if (!NT_STATUS_IS_OK(result))
603                 return result;
604
605         /* Get user handle */
606         result = rpccli_samr_OpenUser(cli, mem_ctx,
607                                       &dom_pol,
608                                       des_access,
609                                       user_rid,
610                                       &user_pol);
611
612         if (!NT_STATUS_IS_OK(result))
613                 return result;
614
615         /* Query user rids */
616         result = rpccli_samr_GetGroupsForUser(cli, mem_ctx,
617                                               &user_pol,
618                                               &rid_array);
619         *num_groups = rid_array->count;
620
621         rpccli_samr_Close(cli, mem_ctx, &user_pol);
622
623         if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0)
624                 return result;
625
626         (*user_grpsids) = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_groups);
627         if (!(*user_grpsids))
628                 return NT_STATUS_NO_MEMORY;
629
630         for (i=0;i<(*num_groups);i++) {
631                 sid_copy(&((*user_grpsids)[i]), &domain->sid);
632                 sid_append_rid(&((*user_grpsids)[i]),
633                                 rid_array->rids[i].rid);
634         }
635
636         return NT_STATUS_OK;
637 }
638
639 #define MAX_SAM_ENTRIES_W2K 0x400 /* 1024 */
640
641 static NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain,
642                                          TALLOC_CTX *mem_ctx,
643                                          uint32 num_sids, const DOM_SID *sids,
644                                          uint32 *num_aliases,
645                                          uint32 **alias_rids)
646 {
647         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
648         POLICY_HND dom_pol;
649         uint32 num_query_sids = 0;
650         int i;
651         struct rpc_pipe_client *cli;
652         struct samr_Ids alias_rids_query;
653         int rangesize = MAX_SAM_ENTRIES_W2K;
654         uint32 total_sids = 0;
655         int num_queries = 1;
656
657         *num_aliases = 0;
658         *alias_rids = NULL;
659
660         DEBUG(3,("rpc: lookup_useraliases\n"));
661
662         if ( !winbindd_can_contact_domain( domain ) ) {
663                 DEBUG(10,("msrpc_lookup_useraliases: No incoming trust for domain %s\n",
664                           domain->name));
665                 return NT_STATUS_OK;
666         }
667
668         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
669         if (!NT_STATUS_IS_OK(result))
670                 return result;
671
672         do {
673                 /* prepare query */
674                 struct lsa_SidArray sid_array;
675
676                 ZERO_STRUCT(sid_array);
677
678                 num_query_sids = MIN(num_sids - total_sids, rangesize);
679
680                 DEBUG(10,("rpc: lookup_useraliases: entering query %d for %d sids\n", 
681                         num_queries, num_query_sids));  
682
683                 if (num_query_sids) {
684                         sid_array.sids = TALLOC_ZERO_ARRAY(mem_ctx, struct lsa_SidPtr, num_query_sids);
685                         if (sid_array.sids == NULL) {
686                                 return NT_STATUS_NO_MEMORY;
687                         }
688                 } else {
689                         sid_array.sids = NULL;
690                 }
691
692                 for (i=0; i<num_query_sids; i++) {
693                         sid_array.sids[i].sid = sid_dup_talloc(mem_ctx, &sids[total_sids++]);
694                         if (!sid_array.sids[i].sid) {
695                                 TALLOC_FREE(sid_array.sids);
696                                 return NT_STATUS_NO_MEMORY;
697                         }
698                 }
699                 sid_array.num_sids = num_query_sids;
700
701                 /* do request */
702                 result = rpccli_samr_GetAliasMembership(cli, mem_ctx,
703                                                         &dom_pol,
704                                                         &sid_array,
705                                                         &alias_rids_query);
706
707                 if (!NT_STATUS_IS_OK(result)) {
708                         *num_aliases = 0;
709                         *alias_rids = NULL;
710                         TALLOC_FREE(sid_array.sids);
711                         goto done;
712                 }
713
714                 /* process output */
715
716                 for (i=0; i<alias_rids_query.count; i++) {
717                         size_t na = *num_aliases;
718                         if (!add_rid_to_array_unique(mem_ctx, alias_rids_query.ids[i],
719                                                 alias_rids, &na)) {
720                                 return NT_STATUS_NO_MEMORY;
721                         }
722                         *num_aliases = na;
723                 }
724
725                 TALLOC_FREE(sid_array.sids);
726
727                 num_queries++;
728
729         } while (total_sids < num_sids);
730
731  done:
732         DEBUG(10,("rpc: lookup_useraliases: got %d aliases in %d queries "
733                 "(rangesize: %d)\n", *num_aliases, num_queries, rangesize));
734
735         return result;
736 }
737
738
739 /* Lookup group membership given a rid.   */
740 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
741                                 TALLOC_CTX *mem_ctx,
742                                 const DOM_SID *group_sid, uint32 *num_names, 
743                                 DOM_SID **sid_mem, char ***names, 
744                                 uint32 **name_types)
745 {
746         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
747         uint32 i, total_names = 0;
748         POLICY_HND dom_pol, group_pol;
749         uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
750         uint32 *rid_mem = NULL;
751         uint32 group_rid;
752         unsigned int j, r;
753         struct rpc_pipe_client *cli;
754         unsigned int orig_timeout;
755         struct samr_RidTypeArray *rids = NULL;
756
757         DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain->name,
758                   sid_string_dbg(group_sid)));
759
760         if ( !winbindd_can_contact_domain( domain ) ) {
761                 DEBUG(10,("lookup_groupmem: No incoming trust for domain %s\n",
762                           domain->name));
763                 return NT_STATUS_OK;
764         }
765
766         if (!sid_peek_check_rid(&domain->sid, group_sid, &group_rid))
767                 return NT_STATUS_UNSUCCESSFUL;
768
769         *num_names = 0;
770
771         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
772         if (!NT_STATUS_IS_OK(result))
773                 return result;
774
775         result = rpccli_samr_OpenGroup(cli, mem_ctx,
776                                        &dom_pol,
777                                        des_access,
778                                        group_rid,
779                                        &group_pol);
780
781         if (!NT_STATUS_IS_OK(result))
782                 return result;
783
784         /* Step #1: Get a list of user rids that are the members of the
785            group. */
786
787         /* This call can take a long time - allow the server to time out.
788            35 seconds should do it. */
789
790         orig_timeout = rpccli_set_timeout(cli, 35000);
791
792         result = rpccli_samr_QueryGroupMember(cli, mem_ctx,
793                                               &group_pol,
794                                               &rids);
795
796         /* And restore our original timeout. */
797         rpccli_set_timeout(cli, orig_timeout);
798
799         rpccli_samr_Close(cli, mem_ctx, &group_pol);
800
801         if (!NT_STATUS_IS_OK(result))
802                 return result;
803
804         *num_names = rids->count;
805         rid_mem = rids->rids;
806
807         if (!*num_names) {
808                 names = NULL;
809                 name_types = NULL;
810                 sid_mem = NULL;
811                 return NT_STATUS_OK;
812         }
813
814         /* Step #2: Convert list of rids into list of usernames.  Do this
815            in bunches of ~1000 to avoid crashing NT4.  It looks like there
816            is a buffer overflow or something like that lurking around
817            somewhere. */
818
819 #define MAX_LOOKUP_RIDS 900
820
821         *names = TALLOC_ZERO_ARRAY(mem_ctx, char *, *num_names);
822         *name_types = TALLOC_ZERO_ARRAY(mem_ctx, uint32, *num_names);
823         *sid_mem = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, *num_names);
824
825         for (j=0;j<(*num_names);j++)
826                 sid_compose(&(*sid_mem)[j], &domain->sid, rid_mem[j]);
827         
828         if (*num_names>0 && (!*names || !*name_types))
829                 return NT_STATUS_NO_MEMORY;
830
831         for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) {
832                 int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS);
833                 struct lsa_Strings tmp_names;
834                 struct samr_Ids tmp_types;
835
836                 /* Lookup a chunk of rids */
837
838                 result = rpccli_samr_LookupRids(cli, mem_ctx,
839                                                 &dom_pol,
840                                                 num_lookup_rids,
841                                                 &rid_mem[i],
842                                                 &tmp_names,
843                                                 &tmp_types);
844
845                 /* see if we have a real error (and yes the
846                    STATUS_SOME_UNMAPPED is the one returned from 2k) */
847
848                 if (!NT_STATUS_IS_OK(result) &&
849                     !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
850                         return result;
851
852                 /* Copy result into array.  The talloc system will take
853                    care of freeing the temporary arrays later on. */
854
855                 if (tmp_names.count != tmp_types.count) {
856                         return NT_STATUS_UNSUCCESSFUL;
857                 }
858
859                 for (r=0; r<tmp_names.count; r++) {
860                         (*names)[i+r] = fill_domain_username_talloc(mem_ctx,
861                                                 domain->name,
862                                                 tmp_names.names[r].string,
863                                                 true);
864                         (*name_types)[i+r] = tmp_types.ids[r];
865                 }
866
867                 total_names += tmp_names.count;
868         }
869
870         *num_names = total_names;
871
872         return NT_STATUS_OK;
873 }
874
875 #ifdef HAVE_LDAP
876
877 #include <ldap.h>
878
879 static int get_ldap_seq(const char *server, int port, uint32 *seq)
880 {
881         int ret = -1;
882         struct timeval to;
883         const char *attrs[] = {"highestCommittedUSN", NULL};
884         LDAPMessage *res = NULL;
885         char **values = NULL;
886         LDAP *ldp = NULL;
887
888         *seq = DOM_SEQUENCE_NONE;
889
890         /*
891          * Parameterised (5) second timeout on open. This is needed as the
892          * search timeout doesn't seem to apply to doing an open as well. JRA.
893          */
894
895         ldp = ldap_open_with_timeout(server, port, lp_ldap_timeout());
896         if (ldp == NULL)
897                 return -1;
898
899         /* Timeout if no response within 20 seconds. */
900         to.tv_sec = 10;
901         to.tv_usec = 0;
902
903         if (ldap_search_st(ldp, "", LDAP_SCOPE_BASE, "(objectclass=*)",
904                            CONST_DISCARD(char **, attrs), 0, &to, &res))
905                 goto done;
906
907         if (ldap_count_entries(ldp, res) != 1)
908                 goto done;
909
910         values = ldap_get_values(ldp, res, "highestCommittedUSN");
911         if (!values || !values[0])
912                 goto done;
913
914         *seq = atoi(values[0]);
915         ret = 0;
916
917   done:
918
919         if (values)
920                 ldap_value_free(values);
921         if (res)
922                 ldap_msgfree(res);
923         if (ldp)
924                 ldap_unbind(ldp);
925         return ret;
926 }
927
928 /**********************************************************************
929  Get the sequence number for a Windows AD native mode domain using
930  LDAP queries.
931 **********************************************************************/
932
933 static int get_ldap_sequence_number(struct winbindd_domain *domain, uint32 *seq)
934 {
935         int ret = -1;
936         char addr[INET6_ADDRSTRLEN];
937
938         print_sockaddr(addr, sizeof(addr), &domain->dcaddr);
939         if ((ret = get_ldap_seq(addr, LDAP_PORT, seq)) == 0) {
940                 DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence "
941                           "number for Domain (%s) from DC (%s)\n",
942                         domain->name, addr));
943         }
944         return ret;
945 }
946
947 #endif /* HAVE_LDAP */
948
949 /* find the sequence number for a domain */
950 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
951 {
952         TALLOC_CTX *mem_ctx;
953         union samr_DomainInfo *info = NULL;
954         NTSTATUS result;
955         POLICY_HND dom_pol;
956         bool got_seq_num = False;
957         struct rpc_pipe_client *cli;
958
959         DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name));
960
961         if ( !winbindd_can_contact_domain( domain ) ) {
962                 DEBUG(10,("sequence_number: No incoming trust for domain %s\n",
963                           domain->name));
964                 *seq = time(NULL);
965                 return NT_STATUS_OK;
966         }
967
968         *seq = DOM_SEQUENCE_NONE;
969
970         if (!(mem_ctx = talloc_init("sequence_number[rpc]")))
971                 return NT_STATUS_NO_MEMORY;
972
973 #ifdef HAVE_LDAP
974         if ( domain->active_directory ) 
975         {
976                 int res;
977
978                 DEBUG(8,("using get_ldap_seq() to retrieve the "
979                          "sequence number\n"));
980
981                 res =  get_ldap_sequence_number( domain, seq );
982                 if (res == 0)
983                 {                       
984                         result = NT_STATUS_OK;
985                         DEBUG(10,("domain_sequence_number: LDAP for "
986                                   "domain %s is %u\n",
987                                   domain->name, *seq));
988                         goto done;
989                 }
990
991                 DEBUG(10,("domain_sequence_number: failed to get LDAP "
992                           "sequence number for domain %s\n",
993                           domain->name ));
994         }
995 #endif /* HAVE_LDAP */
996
997         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
998         if (!NT_STATUS_IS_OK(result)) {
999                 goto done;
1000         }
1001
1002         /* Query domain info */
1003
1004         result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
1005                                              &dom_pol,
1006                                              8,
1007                                              &info);
1008
1009         if (NT_STATUS_IS_OK(result)) {
1010                 *seq = info->info8.sequence_num;
1011                 got_seq_num = True;
1012                 goto seq_num;
1013         }
1014
1015         /* retry with info-level 2 in case the dc does not support info-level 8
1016          * (like all older samba2 and samba3 dc's) - Guenther */
1017
1018         result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
1019                                              &dom_pol,
1020                                              2,
1021                                              &info);
1022
1023         if (NT_STATUS_IS_OK(result)) {
1024                 *seq = info->general.sequence_num;
1025                 got_seq_num = True;
1026         }
1027
1028  seq_num:
1029         if (got_seq_num) {
1030                 DEBUG(10,("domain_sequence_number: for domain %s is %u\n",
1031                           domain->name, (unsigned)*seq));
1032         } else {
1033                 DEBUG(10,("domain_sequence_number: failed to get sequence "
1034                           "number (%u) for domain %s\n",
1035                           (unsigned)*seq, domain->name ));
1036         }
1037
1038   done:
1039
1040         talloc_destroy(mem_ctx);
1041
1042         return result;
1043 }
1044
1045 /* get a list of trusted domains */
1046 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
1047                                 TALLOC_CTX *mem_ctx,
1048                                 uint32 *num_domains,
1049                                 char ***names,
1050                                 char ***alt_names,
1051                                 DOM_SID **dom_sids)
1052 {
1053         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1054         uint32 enum_ctx = 0;
1055         struct rpc_pipe_client *cli;
1056         POLICY_HND lsa_policy;
1057
1058         DEBUG(3,("rpc: trusted_domains\n"));
1059
1060         *num_domains = 0;
1061         *names = NULL;
1062         *alt_names = NULL;
1063         *dom_sids = NULL;
1064
1065         result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
1066         if (!NT_STATUS_IS_OK(result))
1067                 return result;
1068
1069         result = STATUS_MORE_ENTRIES;
1070
1071         while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
1072                 uint32 start_idx;
1073                 int i;
1074                 struct lsa_DomainList dom_list;
1075
1076                 result = rpccli_lsa_EnumTrustDom(cli, mem_ctx,
1077                                                  &lsa_policy,
1078                                                  &enum_ctx,
1079                                                  &dom_list,
1080                                                  (uint32_t)-1);
1081
1082                 if (!NT_STATUS_IS_OK(result) &&
1083                     !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
1084                         break;
1085
1086                 start_idx = *num_domains;
1087                 *num_domains += dom_list.count;
1088                 *names = TALLOC_REALLOC_ARRAY(mem_ctx, *names,
1089                                               char *, *num_domains);
1090                 *dom_sids = TALLOC_REALLOC_ARRAY(mem_ctx, *dom_sids,
1091                                                  DOM_SID, *num_domains);
1092                 *alt_names = TALLOC_REALLOC_ARRAY(mem_ctx, *alt_names,
1093                                                  char *, *num_domains);
1094                 if ((*names == NULL) || (*dom_sids == NULL) ||
1095                     (*alt_names == NULL))
1096                         return NT_STATUS_NO_MEMORY;
1097
1098                 for (i=0; i<dom_list.count; i++) {
1099                         (*names)[start_idx+i] = CONST_DISCARD(char *, dom_list.domains[i].name.string);
1100                         (*dom_sids)[start_idx+i] = *dom_list.domains[i].sid;
1101                         (*alt_names)[start_idx+i] = talloc_strdup(mem_ctx, "");
1102                 }
1103         }
1104         return result;
1105 }
1106
1107 /* find the lockout policy for a domain */
1108 static NTSTATUS msrpc_lockout_policy(struct winbindd_domain *domain,
1109                                      TALLOC_CTX *mem_ctx,
1110                                      struct samr_DomInfo12 *lockout_policy)
1111 {
1112         NTSTATUS result;
1113         struct rpc_pipe_client *cli;
1114         POLICY_HND dom_pol;
1115         union samr_DomainInfo *info = NULL;
1116
1117         DEBUG(10,("rpc: fetch lockout policy for %s\n", domain->name));
1118
1119         if ( !winbindd_can_contact_domain( domain ) ) {
1120                 DEBUG(10,("msrpc_lockout_policy: No incoming trust for domain %s\n",
1121                           domain->name));
1122                 return NT_STATUS_NOT_SUPPORTED;
1123         }
1124
1125         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
1126         if (!NT_STATUS_IS_OK(result)) {
1127                 goto done;
1128         }
1129
1130         result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
1131                                              &dom_pol,
1132                                              12,
1133                                              &info);
1134         if (!NT_STATUS_IS_OK(result)) {
1135                 goto done;
1136         }
1137
1138         *lockout_policy = info->info12;
1139
1140         DEBUG(10,("msrpc_lockout_policy: lockout_threshold %d\n",
1141                 info->info12.lockout_threshold));
1142
1143   done:
1144
1145         return result;
1146 }
1147
1148 /* find the password policy for a domain */
1149 static NTSTATUS msrpc_password_policy(struct winbindd_domain *domain,
1150                                       TALLOC_CTX *mem_ctx,
1151                                       struct samr_DomInfo1 *password_policy)
1152 {
1153         NTSTATUS result;
1154         struct rpc_pipe_client *cli;
1155         POLICY_HND dom_pol;
1156         union samr_DomainInfo *info = NULL;
1157
1158         DEBUG(10,("rpc: fetch password policy for %s\n", domain->name));
1159
1160         if ( !winbindd_can_contact_domain( domain ) ) {
1161                 DEBUG(10,("msrpc_password_policy: No incoming trust for domain %s\n",
1162                           domain->name));
1163                 return NT_STATUS_NOT_SUPPORTED;
1164         }
1165
1166         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
1167         if (!NT_STATUS_IS_OK(result)) {
1168                 goto done;
1169         }
1170
1171         result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
1172                                              &dom_pol,
1173                                              1,
1174                                              &info);
1175         if (!NT_STATUS_IS_OK(result)) {
1176                 goto done;
1177         }
1178
1179         *password_policy = info->info1;
1180
1181         DEBUG(10,("msrpc_password_policy: min_length_password %d\n",
1182                 info->info1.min_password_length));
1183
1184   done:
1185
1186         return result;
1187 }
1188
1189
1190 /* the rpc backend methods are exposed via this structure */
1191 struct winbindd_methods msrpc_methods = {
1192         False,
1193         query_user_list,
1194         enum_dom_groups,
1195         enum_local_groups,
1196         msrpc_name_to_sid,
1197         msrpc_sid_to_name,
1198         msrpc_rids_to_names,
1199         query_user,
1200         lookup_usergroups,
1201         msrpc_lookup_useraliases,
1202         lookup_groupmem,
1203         sequence_number,
1204         msrpc_lockout_policy,
1205         msrpc_password_policy,
1206         trusted_domains,
1207 };