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