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