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