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