Merge branch 'selftest' of git://git.samba.org/jelmer/samba
[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 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 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 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 NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain,
640                                   TALLOC_CTX *mem_ctx,
641                                   uint32 num_sids, const DOM_SID *sids,
642                                   uint32 *num_aliases, uint32 **alias_rids)
643 {
644         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
645         POLICY_HND dom_pol;
646         uint32 num_query_sids = 0;
647         int i;
648         struct rpc_pipe_client *cli;
649         struct samr_Ids alias_rids_query;
650         int rangesize = MAX_SAM_ENTRIES_W2K;
651         uint32 total_sids = 0;
652         int num_queries = 1;
653
654         *num_aliases = 0;
655         *alias_rids = NULL;
656
657         DEBUG(3,("rpc: lookup_useraliases\n"));
658
659         if ( !winbindd_can_contact_domain( domain ) ) {
660                 DEBUG(10,("msrpc_lookup_useraliases: No incoming trust for domain %s\n",
661                           domain->name));
662                 return NT_STATUS_OK;
663         }
664
665         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
666         if (!NT_STATUS_IS_OK(result))
667                 return result;
668
669         do {
670                 /* prepare query */
671                 struct lsa_SidArray sid_array;
672
673                 ZERO_STRUCT(sid_array);
674
675                 num_query_sids = MIN(num_sids - total_sids, rangesize);
676
677                 DEBUG(10,("rpc: lookup_useraliases: entering query %d for %d sids\n", 
678                         num_queries, num_query_sids));  
679
680                 if (num_query_sids) {
681                         sid_array.sids = TALLOC_ZERO_ARRAY(mem_ctx, struct lsa_SidPtr, num_query_sids);
682                         if (sid_array.sids == NULL) {
683                                 return NT_STATUS_NO_MEMORY;
684                         }
685                 } else {
686                         sid_array.sids = NULL;
687                 }
688
689                 for (i=0; i<num_query_sids; i++) {
690                         sid_array.sids[i].sid = sid_dup_talloc(mem_ctx, &sids[total_sids++]);
691                         if (!sid_array.sids[i].sid) {
692                                 TALLOC_FREE(sid_array.sids);
693                                 return NT_STATUS_NO_MEMORY;
694                         }
695                 }
696                 sid_array.num_sids = num_query_sids;
697
698                 /* do request */
699                 result = rpccli_samr_GetAliasMembership(cli, mem_ctx,
700                                                         &dom_pol,
701                                                         &sid_array,
702                                                         &alias_rids_query);
703
704                 if (!NT_STATUS_IS_OK(result)) {
705                         *num_aliases = 0;
706                         *alias_rids = NULL;
707                         TALLOC_FREE(sid_array.sids);
708                         goto done;
709                 }
710
711                 /* process output */
712
713                 for (i=0; i<alias_rids_query.count; i++) {
714                         size_t na = *num_aliases;
715                         if (!add_rid_to_array_unique(mem_ctx, alias_rids_query.ids[i],
716                                                 alias_rids, &na)) {
717                                 return NT_STATUS_NO_MEMORY;
718                         }
719                         *num_aliases = na;
720                 }
721
722                 TALLOC_FREE(sid_array.sids);
723
724                 num_queries++;
725
726         } while (total_sids < num_sids);
727
728  done:
729         DEBUG(10,("rpc: lookup_useraliases: got %d aliases in %d queries "
730                 "(rangesize: %d)\n", *num_aliases, num_queries, rangesize));
731
732         return result;
733 }
734
735
736 /* Lookup group membership given a rid.   */
737 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
738                                 TALLOC_CTX *mem_ctx,
739                                 const DOM_SID *group_sid, uint32 *num_names, 
740                                 DOM_SID **sid_mem, char ***names, 
741                                 uint32 **name_types)
742 {
743         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
744         uint32 i, total_names = 0;
745         POLICY_HND dom_pol, group_pol;
746         uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
747         uint32 *rid_mem = NULL;
748         uint32 group_rid;
749         unsigned int j, r;
750         struct rpc_pipe_client *cli;
751         unsigned int orig_timeout;
752         struct samr_RidTypeArray *rids = NULL;
753
754         DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain->name,
755                   sid_string_dbg(group_sid)));
756
757         if ( !winbindd_can_contact_domain( domain ) ) {
758                 DEBUG(10,("lookup_groupmem: No incoming trust for domain %s\n",
759                           domain->name));
760                 return NT_STATUS_OK;
761         }
762
763         if (!sid_peek_check_rid(&domain->sid, group_sid, &group_rid))
764                 return NT_STATUS_UNSUCCESSFUL;
765
766         *num_names = 0;
767
768         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
769         if (!NT_STATUS_IS_OK(result))
770                 return result;
771
772         result = rpccli_samr_OpenGroup(cli, mem_ctx,
773                                        &dom_pol,
774                                        des_access,
775                                        group_rid,
776                                        &group_pol);
777
778         if (!NT_STATUS_IS_OK(result))
779                 return result;
780
781         /* Step #1: Get a list of user rids that are the members of the
782            group. */
783
784         /* This call can take a long time - allow the server to time out.
785            35 seconds should do it. */
786
787         orig_timeout = rpccli_set_timeout(cli, 35000);
788
789         result = rpccli_samr_QueryGroupMember(cli, mem_ctx,
790                                               &group_pol,
791                                               &rids);
792
793         /* And restore our original timeout. */
794         rpccli_set_timeout(cli, orig_timeout);
795
796         rpccli_samr_Close(cli, mem_ctx, &group_pol);
797
798         if (!NT_STATUS_IS_OK(result))
799                 return result;
800
801         *num_names = rids->count;
802         rid_mem = rids->rids;
803
804         if (!*num_names) {
805                 names = NULL;
806                 name_types = NULL;
807                 sid_mem = NULL;
808                 return NT_STATUS_OK;
809         }
810
811         /* Step #2: Convert list of rids into list of usernames.  Do this
812            in bunches of ~1000 to avoid crashing NT4.  It looks like there
813            is a buffer overflow or something like that lurking around
814            somewhere. */
815
816 #define MAX_LOOKUP_RIDS 900
817
818         *names = TALLOC_ZERO_ARRAY(mem_ctx, char *, *num_names);
819         *name_types = TALLOC_ZERO_ARRAY(mem_ctx, uint32, *num_names);
820         *sid_mem = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, *num_names);
821
822         for (j=0;j<(*num_names);j++)
823                 sid_compose(&(*sid_mem)[j], &domain->sid, rid_mem[j]);
824         
825         if (*num_names>0 && (!*names || !*name_types))
826                 return NT_STATUS_NO_MEMORY;
827
828         for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) {
829                 int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS);
830                 struct lsa_Strings tmp_names;
831                 struct samr_Ids tmp_types;
832
833                 /* Lookup a chunk of rids */
834
835                 result = rpccli_samr_LookupRids(cli, mem_ctx,
836                                                 &dom_pol,
837                                                 num_lookup_rids,
838                                                 &rid_mem[i],
839                                                 &tmp_names,
840                                                 &tmp_types);
841
842                 /* see if we have a real error (and yes the
843                    STATUS_SOME_UNMAPPED is the one returned from 2k) */
844
845                 if (!NT_STATUS_IS_OK(result) &&
846                     !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
847                         return result;
848
849                 /* Copy result into array.  The talloc system will take
850                    care of freeing the temporary arrays later on. */
851
852                 if (tmp_names.count != tmp_types.count) {
853                         return NT_STATUS_UNSUCCESSFUL;
854                 }
855
856                 for (r=0; r<tmp_names.count; r++) {
857                         (*names)[i+r] = fill_domain_username_talloc(mem_ctx,
858                                                 domain->name,
859                                                 tmp_names.names[r].string,
860                                                 true);
861                         (*name_types)[i+r] = tmp_types.ids[r];
862                 }
863
864                 total_names += tmp_names.count;
865         }
866
867         *num_names = total_names;
868
869         return NT_STATUS_OK;
870 }
871
872 #ifdef HAVE_LDAP
873
874 #include <ldap.h>
875
876 static int get_ldap_seq(const char *server, int port, uint32 *seq)
877 {
878         int ret = -1;
879         struct timeval to;
880         const char *attrs[] = {"highestCommittedUSN", NULL};
881         LDAPMessage *res = NULL;
882         char **values = NULL;
883         LDAP *ldp = NULL;
884
885         *seq = DOM_SEQUENCE_NONE;
886
887         /*
888          * Parameterised (5) second timeout on open. This is needed as the
889          * search timeout doesn't seem to apply to doing an open as well. JRA.
890          */
891
892         ldp = ldap_open_with_timeout(server, port, lp_ldap_timeout());
893         if (ldp == NULL)
894                 return -1;
895
896         /* Timeout if no response within 20 seconds. */
897         to.tv_sec = 10;
898         to.tv_usec = 0;
899
900         if (ldap_search_st(ldp, "", LDAP_SCOPE_BASE, "(objectclass=*)",
901                            CONST_DISCARD(char **, attrs), 0, &to, &res))
902                 goto done;
903
904         if (ldap_count_entries(ldp, res) != 1)
905                 goto done;
906
907         values = ldap_get_values(ldp, res, "highestCommittedUSN");
908         if (!values || !values[0])
909                 goto done;
910
911         *seq = atoi(values[0]);
912         ret = 0;
913
914   done:
915
916         if (values)
917                 ldap_value_free(values);
918         if (res)
919                 ldap_msgfree(res);
920         if (ldp)
921                 ldap_unbind(ldp);
922         return ret;
923 }
924
925 /**********************************************************************
926  Get the sequence number for a Windows AD native mode domain using
927  LDAP queries.
928 **********************************************************************/
929
930 static int get_ldap_sequence_number(struct winbindd_domain *domain, uint32 *seq)
931 {
932         int ret = -1;
933         char addr[INET6_ADDRSTRLEN];
934
935         print_sockaddr(addr, sizeof(addr), &domain->dcaddr);
936         if ((ret = get_ldap_seq(addr, LDAP_PORT, seq)) == 0) {
937                 DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence "
938                           "number for Domain (%s) from DC (%s)\n",
939                         domain->name, addr));
940         }
941         return ret;
942 }
943
944 #endif /* HAVE_LDAP */
945
946 /* find the sequence number for a domain */
947 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
948 {
949         TALLOC_CTX *mem_ctx;
950         union samr_DomainInfo *info = NULL;
951         NTSTATUS result;
952         POLICY_HND dom_pol;
953         bool got_seq_num = False;
954         struct rpc_pipe_client *cli;
955
956         DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name));
957
958         if ( !winbindd_can_contact_domain( domain ) ) {
959                 DEBUG(10,("sequence_number: No incoming trust for domain %s\n",
960                           domain->name));
961                 *seq = time(NULL);
962                 return NT_STATUS_OK;
963         }
964
965         *seq = DOM_SEQUENCE_NONE;
966
967         if (!(mem_ctx = talloc_init("sequence_number[rpc]")))
968                 return NT_STATUS_NO_MEMORY;
969
970 #ifdef HAVE_LDAP
971         if ( domain->active_directory ) 
972         {
973                 int res;
974
975                 DEBUG(8,("using get_ldap_seq() to retrieve the "
976                          "sequence number\n"));
977
978                 res =  get_ldap_sequence_number( domain, seq );
979                 if (res == 0)
980                 {                       
981                         result = NT_STATUS_OK;
982                         DEBUG(10,("domain_sequence_number: LDAP for "
983                                   "domain %s is %u\n",
984                                   domain->name, *seq));
985                         goto done;
986                 }
987
988                 DEBUG(10,("domain_sequence_number: failed to get LDAP "
989                           "sequence number for domain %s\n",
990                           domain->name ));
991         }
992 #endif /* HAVE_LDAP */
993
994         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
995         if (!NT_STATUS_IS_OK(result)) {
996                 goto done;
997         }
998
999         /* Query domain info */
1000
1001         result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
1002                                              &dom_pol,
1003                                              8,
1004                                              &info);
1005
1006         if (NT_STATUS_IS_OK(result)) {
1007                 *seq = info->info8.sequence_num;
1008                 got_seq_num = True;
1009                 goto seq_num;
1010         }
1011
1012         /* retry with info-level 2 in case the dc does not support info-level 8
1013          * (like all older samba2 and samba3 dc's) - Guenther */
1014
1015         result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
1016                                              &dom_pol,
1017                                              2,
1018                                              &info);
1019
1020         if (NT_STATUS_IS_OK(result)) {
1021                 *seq = info->general.sequence_num;
1022                 got_seq_num = True;
1023         }
1024
1025  seq_num:
1026         if (got_seq_num) {
1027                 DEBUG(10,("domain_sequence_number: for domain %s is %u\n",
1028                           domain->name, (unsigned)*seq));
1029         } else {
1030                 DEBUG(10,("domain_sequence_number: failed to get sequence "
1031                           "number (%u) for domain %s\n",
1032                           (unsigned)*seq, domain->name ));
1033         }
1034
1035   done:
1036
1037         talloc_destroy(mem_ctx);
1038
1039         return result;
1040 }
1041
1042 /* get a list of trusted domains */
1043 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
1044                                 TALLOC_CTX *mem_ctx,
1045                                 uint32 *num_domains,
1046                                 char ***names,
1047                                 char ***alt_names,
1048                                 DOM_SID **dom_sids)
1049 {
1050         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1051         uint32 enum_ctx = 0;
1052         struct rpc_pipe_client *cli;
1053         POLICY_HND lsa_policy;
1054
1055         DEBUG(3,("rpc: trusted_domains\n"));
1056
1057         *num_domains = 0;
1058         *names = NULL;
1059         *alt_names = NULL;
1060         *dom_sids = NULL;
1061
1062         result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
1063         if (!NT_STATUS_IS_OK(result))
1064                 return result;
1065
1066         result = STATUS_MORE_ENTRIES;
1067
1068         while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
1069                 uint32 start_idx;
1070                 int i;
1071                 struct lsa_DomainList dom_list;
1072
1073                 result = rpccli_lsa_EnumTrustDom(cli, mem_ctx,
1074                                                  &lsa_policy,
1075                                                  &enum_ctx,
1076                                                  &dom_list,
1077                                                  (uint32_t)-1);
1078
1079                 if (!NT_STATUS_IS_OK(result) &&
1080                     !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
1081                         break;
1082
1083                 start_idx = *num_domains;
1084                 *num_domains += dom_list.count;
1085                 *names = TALLOC_REALLOC_ARRAY(mem_ctx, *names,
1086                                               char *, *num_domains);
1087                 *dom_sids = TALLOC_REALLOC_ARRAY(mem_ctx, *dom_sids,
1088                                                  DOM_SID, *num_domains);
1089                 *alt_names = TALLOC_REALLOC_ARRAY(mem_ctx, *alt_names,
1090                                                  char *, *num_domains);
1091                 if ((*names == NULL) || (*dom_sids == NULL) ||
1092                     (*alt_names == NULL))
1093                         return NT_STATUS_NO_MEMORY;
1094
1095                 for (i=0; i<dom_list.count; i++) {
1096                         (*names)[start_idx+i] = CONST_DISCARD(char *, dom_list.domains[i].name.string);
1097                         (*dom_sids)[start_idx+i] = *dom_list.domains[i].sid;
1098                         (*alt_names)[start_idx+i] = talloc_strdup(mem_ctx, "");
1099                 }
1100         }
1101         return result;
1102 }
1103
1104 /* find the lockout policy for a domain */
1105 NTSTATUS msrpc_lockout_policy(struct winbindd_domain *domain,
1106                               TALLOC_CTX *mem_ctx,
1107                               struct samr_DomInfo12 *lockout_policy)
1108 {
1109         NTSTATUS result;
1110         struct rpc_pipe_client *cli;
1111         POLICY_HND dom_pol;
1112         union samr_DomainInfo *info = NULL;
1113
1114         DEBUG(10,("rpc: fetch lockout policy for %s\n", domain->name));
1115
1116         if ( !winbindd_can_contact_domain( domain ) ) {
1117                 DEBUG(10,("msrpc_lockout_policy: No incoming trust for domain %s\n",
1118                           domain->name));
1119                 return NT_STATUS_NOT_SUPPORTED;
1120         }
1121
1122         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
1123         if (!NT_STATUS_IS_OK(result)) {
1124                 goto done;
1125         }
1126
1127         result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
1128                                              &dom_pol,
1129                                              12,
1130                                              &info);
1131         if (!NT_STATUS_IS_OK(result)) {
1132                 goto done;
1133         }
1134
1135         *lockout_policy = info->info12;
1136
1137         DEBUG(10,("msrpc_lockout_policy: lockout_threshold %d\n",
1138                 info->info12.lockout_threshold));
1139
1140   done:
1141
1142         return result;
1143 }
1144
1145 /* find the password policy for a domain */
1146 NTSTATUS msrpc_password_policy(struct winbindd_domain *domain,
1147                                TALLOC_CTX *mem_ctx,
1148                                struct samr_DomInfo1 *password_policy)
1149 {
1150         NTSTATUS result;
1151         struct rpc_pipe_client *cli;
1152         POLICY_HND dom_pol;
1153         union samr_DomainInfo *info = NULL;
1154
1155         DEBUG(10,("rpc: fetch password policy for %s\n", domain->name));
1156
1157         if ( !winbindd_can_contact_domain( domain ) ) {
1158                 DEBUG(10,("msrpc_password_policy: No incoming trust for domain %s\n",
1159                           domain->name));
1160                 return NT_STATUS_NOT_SUPPORTED;
1161         }
1162
1163         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
1164         if (!NT_STATUS_IS_OK(result)) {
1165                 goto done;
1166         }
1167
1168         result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
1169                                              &dom_pol,
1170                                              1,
1171                                              &info);
1172         if (!NT_STATUS_IS_OK(result)) {
1173                 goto done;
1174         }
1175
1176         *password_policy = info->info1;
1177
1178         DEBUG(10,("msrpc_password_policy: min_length_password %d\n",
1179                 info->info1.min_password_length));
1180
1181   done:
1182
1183         return result;
1184 }
1185
1186
1187 /* the rpc backend methods are exposed via this structure */
1188 struct winbindd_methods msrpc_methods = {
1189         False,
1190         query_user_list,
1191         enum_dom_groups,
1192         enum_local_groups,
1193         msrpc_name_to_sid,
1194         msrpc_sid_to_name,
1195         msrpc_rids_to_names,
1196         query_user,
1197         lookup_usergroups,
1198         msrpc_lookup_useraliases,
1199         lookup_groupmem,
1200         sequence_number,
1201         msrpc_lockout_policy,
1202         msrpc_password_policy,
1203         trusted_domains,
1204 };