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