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