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