This commit was manufactured by cvs2svn to create branch 'SAMBA_3_0'.(This used to...
[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
7    Copyright (C) Andrew Tridgell 2001
8    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include "winbindd.h"
25
26 #undef DBGC_CLASS
27 #define DBGC_CLASS DBGC_WINBIND
28
29 /* Query display info for a domain.  This returns enough information plus a
30    bit extra to give an overview of domain users for the User Manager
31    application. */
32 static NTSTATUS query_user_list(struct winbindd_domain *domain,
33                                TALLOC_CTX *mem_ctx,
34                                uint32 *num_entries, 
35                                WINBIND_USERINFO **info)
36 {
37         CLI_POLICY_HND *hnd;
38         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
39         POLICY_HND dom_pol;
40         BOOL got_dom_pol = False;
41         uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
42         int i, loop_count = 0;
43         int retry;
44
45         DEBUG(3,("rpc: query_user_list\n"));
46
47         *num_entries = 0;
48         *info = NULL;
49
50         /* Get sam handle */
51
52         retry = 0;
53         do {
54                 if (!(hnd = cm_get_sam_handle(domain->name)))
55                         goto done;
56
57                 /* Get domain handle */
58
59                 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
60                                                 des_access, &domain->sid, &dom_pol);
61
62         } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
63
64         if (!NT_STATUS_IS_OK(result))
65                 goto done;
66
67         got_dom_pol = True;
68
69         i = 0;
70         do {
71                 SAM_DISPINFO_CTR ctr;
72                 SAM_DISPINFO_1 info1;
73                 uint32 count = 0, start=i, max_entries, max_size;
74                 int j;
75                 TALLOC_CTX *ctx2;
76
77                 ctr.sam.info1 = &info1;
78
79                 ctx2 = talloc_init("winbindd dispinfo");
80                 if (!ctx2) {
81                         result = NT_STATUS_NO_MEMORY;
82                         goto done;
83                 }
84                 
85                 get_query_dispinfo_params(
86                         loop_count, &max_entries, &max_size);
87
88                 /* Query display info level 1 */
89                 result = cli_samr_query_dispinfo(
90                         hnd->cli, ctx2, &dom_pol, &start, 1, &count, 
91                         max_entries, max_size, &ctr);
92
93                 loop_count++;
94
95                 if (!NT_STATUS_IS_OK(result) && 
96                     !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) break;
97
98                 (*num_entries) += count;
99
100                 /* now map the result into the WINBIND_USERINFO structure */
101                 (*info) = talloc_realloc(mem_ctx, *info,
102                                          (*num_entries)*sizeof(WINBIND_USERINFO));
103                 if (!(*info)) {
104                         result = NT_STATUS_NO_MEMORY;
105                         talloc_destroy(ctx2);
106                         goto done;
107                 }
108
109                 for (j=0;j<count;i++, j++) {
110                         (*info)[i].acct_name = unistr2_tdup(mem_ctx, &info1.str[j].uni_acct_name);
111                         (*info)[i].full_name = unistr2_tdup(mem_ctx, &info1.str[j].uni_full_name);
112                         (*info)[i].user_rid = info1.sam[j].rid_user;
113                         /* For the moment we set the primary group for
114                            every user to be the Domain Users group.
115                            There are serious problems with determining
116                            the actual primary group for large domains.
117                            This should really be made into a 'winbind
118                            force group' smb.conf parameter or
119                            something like that. */
120                         (*info)[i].group_rid = DOMAIN_GROUP_RID_USERS;
121                 }
122
123                 talloc_destroy(ctx2);
124         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
125
126  done:
127
128         if (got_dom_pol)
129                 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
130
131         return result;
132 }
133
134 /* list all domain groups */
135 static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
136                                 TALLOC_CTX *mem_ctx,
137                                 uint32 *num_entries, 
138                                 struct acct_info **info)
139 {
140         uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
141         CLI_POLICY_HND *hnd;
142         POLICY_HND dom_pol;
143         NTSTATUS status;
144         uint32 start = 0;
145         int retry;
146
147         *num_entries = 0;
148         *info = NULL;
149
150         DEBUG(3,("rpc: enum_dom_groups\n"));
151
152         retry = 0;
153         do {
154                 if (!(hnd = cm_get_sam_handle(domain->name)))
155                         return NT_STATUS_UNSUCCESSFUL;
156
157                 status = cli_samr_open_domain(hnd->cli, mem_ctx,
158                                               &hnd->pol, des_access, &domain->sid, &dom_pol);
159         } while (!NT_STATUS_IS_OK(status) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
160
161         if (!NT_STATUS_IS_OK(status))
162                 return status;
163
164         do {
165                 struct acct_info *info2 = NULL;
166                 uint32 count = 0;
167                 TALLOC_CTX *mem_ctx2;
168
169                 mem_ctx2 = talloc_init("enum_dom_groups[rpc]");
170
171                 /* start is updated by this call. */
172                 status = cli_samr_enum_dom_groups(hnd->cli, mem_ctx2, &dom_pol,
173                                                   &start,
174                                                   0xFFFF, /* buffer size? */
175                                                   &info2, &count);
176
177                 if (!NT_STATUS_IS_OK(status) && 
178                     !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
179                         talloc_destroy(mem_ctx2);
180                         break;
181                 }
182
183                 (*info) = talloc_realloc(mem_ctx, *info, 
184                                          sizeof(**info) * ((*num_entries) + count));
185                 if (! *info) {
186                         talloc_destroy(mem_ctx2);
187                         cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
188                         return NT_STATUS_NO_MEMORY;
189                 }
190
191                 memcpy(&(*info)[*num_entries], info2, count*sizeof(*info2));
192                 (*num_entries) += count;
193                 talloc_destroy(mem_ctx2);
194         } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
195
196         cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
197
198         return status;
199 }
200
201 /* List all domain groups */
202
203 static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
204                                 TALLOC_CTX *mem_ctx,
205                                 uint32 *num_entries, 
206                                 struct acct_info **info)
207 {
208         uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
209         CLI_POLICY_HND *hnd;
210         POLICY_HND dom_pol;
211         NTSTATUS result;
212         int retry;
213
214         *num_entries = 0;
215         *info = NULL;
216
217         retry = 0;
218         do {
219                 if ( !(hnd = cm_get_sam_handle(domain->name)) )
220                         return NT_STATUS_UNSUCCESSFUL;
221
222                 result = cli_samr_open_domain( hnd->cli, mem_ctx, &hnd->pol, 
223                                                 des_access, &domain->sid, &dom_pol);
224         } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
225
226         if ( !NT_STATUS_IS_OK(result))
227                 return result;
228
229         do {
230                 struct acct_info *info2 = NULL;
231                 uint32 count = 0, start = *num_entries;
232                 TALLOC_CTX *mem_ctx2;
233
234                 mem_ctx2 = talloc_init("enum_dom_local_groups[rpc]");
235
236                 result = cli_samr_enum_als_groups( hnd->cli, mem_ctx2, &dom_pol,
237                                           &start, 0xFFFF, &info2, &count);
238                                           
239                 if ( !NT_STATUS_IS_OK(result) 
240                         && !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES) ) 
241                 {
242                         talloc_destroy(mem_ctx2);
243                         break;
244                 }
245
246                 (*info) = talloc_realloc(mem_ctx, *info, 
247                                          sizeof(**info) * ((*num_entries) + count));
248                 if (! *info) {
249                         talloc_destroy(mem_ctx2);
250                         cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
251                         return NT_STATUS_NO_MEMORY;
252                 }
253
254                 memcpy(&(*info)[*num_entries], info2, count*sizeof(*info2));
255                 (*num_entries) += count;
256                 talloc_destroy(mem_ctx2);
257         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
258
259         cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
260
261         return result;
262 }
263
264 /* convert a single name to a sid in a domain */
265 static NTSTATUS name_to_sid(struct winbindd_domain *domain,
266                             const char *name,
267                             DOM_SID *sid,
268                             enum SID_NAME_USE *type)
269 {
270         TALLOC_CTX *mem_ctx;
271         CLI_POLICY_HND *hnd;
272         NTSTATUS status;
273         DOM_SID *sids = NULL;
274         uint32 *types = NULL;
275         const char *full_name;
276         int retry;
277
278         DEBUG(3,("rpc: name_to_sid name=%s\n", name));
279
280         if (!(mem_ctx = talloc_init("name_to_sid[rpc] for [%s]\\[%s]", domain->name, name))) {
281                 DEBUG(0, ("talloc_init failed!\n"));
282                 return NT_STATUS_NO_MEMORY;
283         }
284         
285         full_name = talloc_asprintf(mem_ctx, "%s\\%s", domain->name, name);
286         
287         if (!full_name) {
288                 DEBUG(0, ("talloc_asprintf failed!\n"));
289                 talloc_destroy(mem_ctx);
290                 return NT_STATUS_NO_MEMORY;
291         }
292
293         retry = 0;
294         do {
295                 if (!(hnd = cm_get_lsa_handle(domain->name))) {
296                         talloc_destroy(mem_ctx);
297                         return NT_STATUS_UNSUCCESSFUL;
298                 }
299         
300                 status = cli_lsa_lookup_names(hnd->cli, mem_ctx, &hnd->pol, 1, 
301                                               &full_name, &sids, &types);
302         } while (!NT_STATUS_IS_OK(status) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
303         
304         /* Return rid and type if lookup successful */
305
306         if (NT_STATUS_IS_OK(status)) {
307                 sid_copy(sid, &sids[0]);
308                 *type = types[0];
309         }
310
311         talloc_destroy(mem_ctx);
312         return status;
313 }
314
315 /*
316   convert a domain SID to a user or group name
317 */
318 static NTSTATUS sid_to_name(struct winbindd_domain *domain,
319                             TALLOC_CTX *mem_ctx,
320                             DOM_SID *sid,
321                             char **name,
322                             enum SID_NAME_USE *type)
323 {
324         CLI_POLICY_HND *hnd;
325         char **domains;
326         char **names;
327         uint32 *types;
328         NTSTATUS status;
329         int retry;
330
331         DEBUG(3,("rpc: sid_to_name\n"));
332
333         retry = 0;
334         do {
335                 if (!(hnd = cm_get_lsa_handle(domain->name)))
336                         return NT_STATUS_UNSUCCESSFUL;
337         
338                 status = cli_lsa_lookup_sids(hnd->cli, mem_ctx, &hnd->pol,
339                                              1, sid, &domains, &names, &types);
340         } while (!NT_STATUS_IS_OK(status) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
341
342         if (NT_STATUS_IS_OK(status)) {
343                 *type = types[0];
344                 *name = names[0];
345                 DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name));
346
347                 /* Paranoia */
348                 if (strcasecmp(domain->name, domains[0]) != 0) {
349                         DEBUG(1, ("domain name from domain param and PDC lookup return differ! (%s vs %s)\n", domain->name, domains[0]));
350                         return NT_STATUS_UNSUCCESSFUL;
351                 }
352         }
353         return status;
354 }
355
356 /* Lookup user information from a rid or username. */
357 static NTSTATUS query_user(struct winbindd_domain *domain, 
358                            TALLOC_CTX *mem_ctx, 
359                            uint32 user_rid, 
360                            WINBIND_USERINFO *user_info)
361 {
362         CLI_POLICY_HND *hnd;
363         NTSTATUS result;
364         POLICY_HND dom_pol, user_pol;
365         BOOL got_dom_pol = False, got_user_pol = False;
366         SAM_USERINFO_CTR *ctr;
367         int retry;
368
369         DEBUG(3,("rpc: query_user rid=%u\n", user_rid));
370
371         retry = 0;
372         do {
373                 /* Get sam handle */
374                 if (!(hnd = cm_get_sam_handle(domain->name)))
375                         goto done;
376
377                 /* Get domain handle */
378
379                 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
380                                               SEC_RIGHTS_MAXIMUM_ALLOWED, 
381                                               &domain->sid, &dom_pol);
382         } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
383
384         if (!NT_STATUS_IS_OK(result))
385                 goto done;
386
387         got_dom_pol = True;
388
389         /* Get user handle */
390         result = cli_samr_open_user(hnd->cli, mem_ctx, &dom_pol,
391                                     SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid, &user_pol);
392
393         if (!NT_STATUS_IS_OK(result))
394                 goto done;
395
396         got_user_pol = True;
397
398         /* Get user info */
399         result = cli_samr_query_userinfo(hnd->cli, mem_ctx, &user_pol, 
400                                          0x15, &ctr);
401
402         if (!NT_STATUS_IS_OK(result))
403                 goto done;
404
405         cli_samr_close(hnd->cli, mem_ctx, &user_pol);
406         got_user_pol = False;
407
408         user_info->user_rid = user_rid;
409         user_info->group_rid = ctr->info.id21->group_rid;
410         user_info->acct_name = unistr2_tdup(mem_ctx, 
411                                             &ctr->info.id21->uni_user_name);
412         user_info->full_name = unistr2_tdup(mem_ctx, 
413                                             &ctr->info.id21->uni_full_name);
414
415  done:
416         /* Clean up policy handles */
417         if (got_user_pol)
418                 cli_samr_close(hnd->cli, mem_ctx, &user_pol);
419
420         if (got_dom_pol)
421                 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
422
423         return result;
424 }                                   
425
426 /* Lookup groups a user is a member of.  I wish Unix had a call like this! */
427 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
428                                   TALLOC_CTX *mem_ctx,
429                                   uint32 user_rid, 
430                                   uint32 *num_groups, uint32 **user_gids)
431 {
432         CLI_POLICY_HND *hnd;
433         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
434         POLICY_HND dom_pol, user_pol;
435         uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
436         BOOL got_dom_pol = False, got_user_pol = False;
437         DOM_GID *user_groups;
438         int i;
439         int retry;
440
441         DEBUG(3,("rpc: lookup_usergroups rid=%u\n", user_rid));
442
443         *num_groups = 0;
444
445         /* First try cached universal groups from logon */
446         *user_gids = uni_group_cache_fetch(&domain->sid, user_rid, mem_ctx, num_groups);
447         if((*num_groups > 0) && *user_gids) {
448                 return NT_STATUS_OK;
449         } else {
450             *user_gids = NULL;
451             *num_groups = 0;
452         }
453
454         retry = 0;
455         do {
456                 /* Get sam handle */
457                 if (!(hnd = cm_get_sam_handle(domain->name)))
458                         goto done;
459
460                 /* Get domain handle */
461                 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
462                                                 des_access, &domain->sid, &dom_pol);
463         } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
464
465         if (!NT_STATUS_IS_OK(result))
466                 goto done;
467
468         got_dom_pol = True;
469
470         /* Get user handle */
471         result = cli_samr_open_user(hnd->cli, mem_ctx, &dom_pol,
472                                         des_access, user_rid, &user_pol);
473
474         if (!NT_STATUS_IS_OK(result))
475                 goto done;
476
477         got_user_pol = True;
478
479         /* Query user rids */
480         result = cli_samr_query_usergroups(hnd->cli, mem_ctx, &user_pol, 
481                                            num_groups, &user_groups);
482
483         if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0)
484                 goto done;
485
486         (*user_gids) = talloc(mem_ctx, sizeof(uint32) * (*num_groups));
487         for (i=0;i<(*num_groups);i++) {
488                 (*user_gids)[i] = user_groups[i].g_rid;
489         }
490         
491  done:
492         /* Clean up policy handles */
493         if (got_user_pol)
494                 cli_samr_close(hnd->cli, mem_ctx, &user_pol);
495
496         if (got_dom_pol)
497                 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
498
499         return result;
500 }
501
502
503 /* Lookup group membership given a rid.   */
504 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
505                                 TALLOC_CTX *mem_ctx,
506                                 uint32 group_rid, uint32 *num_names, 
507                                 uint32 **rid_mem, char ***names, 
508                                 uint32 **name_types)
509 {
510         CLI_POLICY_HND *hnd;
511         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
512         uint32 i, total_names = 0;
513         POLICY_HND dom_pol, group_pol;
514         uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
515         BOOL got_dom_pol = False, got_group_pol = False;
516         int retry;
517
518         DEBUG(10,("rpc: lookup_groupmem %s rid=%u\n", domain->name, group_rid));
519
520         *num_names = 0;
521
522         retry = 0;
523         do {
524                 /* Get sam handle */
525                 if (!(hnd = cm_get_sam_handle(domain->name)))
526                         goto done;
527
528                 /* Get domain handle */
529
530                 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
531                                 des_access, &domain->sid, &dom_pol);
532         } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
533
534         if (!NT_STATUS_IS_OK(result))
535                 goto done;
536
537         got_dom_pol = True;
538
539         /* Get group handle */
540
541         result = cli_samr_open_group(hnd->cli, mem_ctx, &dom_pol,
542                                      des_access, group_rid, &group_pol);
543
544         if (!NT_STATUS_IS_OK(result))
545                 goto done;
546
547         got_group_pol = True;
548
549         /* Step #1: Get a list of user rids that are the members of the
550            group. */
551
552         result = cli_samr_query_groupmem(hnd->cli, mem_ctx,
553                                          &group_pol, num_names, rid_mem,
554                                          name_types);
555
556         if (!NT_STATUS_IS_OK(result))
557                 goto done;
558
559         /* Step #2: Convert list of rids into list of usernames.  Do this
560            in bunches of ~1000 to avoid crashing NT4.  It looks like there
561            is a buffer overflow or something like that lurking around
562            somewhere. */
563
564 #define MAX_LOOKUP_RIDS 900
565
566         *names = talloc_zero(mem_ctx, *num_names * sizeof(char *));
567         *name_types = talloc_zero(mem_ctx, *num_names * sizeof(uint32));
568
569         for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) {
570                 int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS);
571                 uint32 tmp_num_names = 0;
572                 char **tmp_names = NULL;
573                 uint32 *tmp_types = NULL;
574
575                 /* Lookup a chunk of rids */
576
577                 result = cli_samr_lookup_rids(hnd->cli, mem_ctx,
578                                               &dom_pol, 1000, /* flags */
579                                               num_lookup_rids,
580                                               &(*rid_mem)[i],
581                                               &tmp_num_names,
582                                               &tmp_names, &tmp_types);
583
584                 if (!NT_STATUS_IS_OK(result))
585                         goto done;
586
587                 /* Copy result into array.  The talloc system will take
588                    care of freeing the temporary arrays later on. */
589
590                 memcpy(&(*names)[i], tmp_names, sizeof(char *) * 
591                        tmp_num_names);
592
593                 memcpy(&(*name_types)[i], tmp_types, sizeof(uint32) *
594                        tmp_num_names);
595
596                 total_names += tmp_num_names;
597         }
598
599         *num_names = total_names;
600
601  done:
602         if (got_group_pol)
603                 cli_samr_close(hnd->cli, mem_ctx, &group_pol);
604
605         if (got_dom_pol)
606                 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
607
608         return result;
609 }
610
611 /* find the sequence number for a domain */
612 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
613 {
614         TALLOC_CTX *mem_ctx;
615         CLI_POLICY_HND *hnd;
616         SAM_UNK_CTR ctr;
617         uint16 switch_value = 2;
618         NTSTATUS result;
619         uint32 seqnum = DOM_SEQUENCE_NONE;
620         POLICY_HND dom_pol;
621         BOOL got_dom_pol = False;
622         uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
623         int retry;
624
625         DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name));
626
627         *seq = DOM_SEQUENCE_NONE;
628
629         if (!(mem_ctx = talloc_init("sequence_number[rpc]")))
630                 return NT_STATUS_NO_MEMORY;
631
632         retry = 0;
633         do {
634                 /* Get sam handle */
635                 if (!(hnd = cm_get_sam_handle(domain->name)))
636                         goto done;
637
638                 /* Get domain handle */
639                 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol, 
640                                       des_access, &domain->sid, &dom_pol);
641         } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
642
643         if (!NT_STATUS_IS_OK(result))
644                 goto done;
645
646         got_dom_pol = True;
647
648         /* Query domain info */
649
650         result = cli_samr_query_dom_info(hnd->cli, mem_ctx, &dom_pol,
651                                          switch_value, &ctr);
652
653         if (NT_STATUS_IS_OK(result)) {
654                 seqnum = ctr.info.inf2.seq_num;
655                 DEBUG(10,("domain_sequence_number: for domain %s is %u\n", domain->name, (unsigned)seqnum ));
656         } else {
657                 DEBUG(10,("domain_sequence_number: failed to get sequence number (%u) for domain %s\n",
658                         (unsigned)seqnum, domain->name ));
659         }
660
661   done:
662
663         if (got_dom_pol)
664                 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
665
666         talloc_destroy(mem_ctx);
667
668         *seq = seqnum;
669
670         return result;
671 }
672
673 /* get a list of trusted domains */
674 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
675                                 TALLOC_CTX *mem_ctx,
676                                 uint32 *num_domains,
677                                 char ***names,
678                                 char ***alt_names,
679                                 DOM_SID **dom_sids)
680 {
681         CLI_POLICY_HND *hnd;
682         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
683         uint32 enum_ctx = 0;
684         int retry;
685
686         DEBUG(3,("rpc: trusted_domains\n"));
687
688         *num_domains = 0;
689         *alt_names = NULL;
690
691         retry = 0;
692         do {
693                 if (!(hnd = cm_get_lsa_handle(lp_workgroup())))
694                         goto done;
695
696                 result = cli_lsa_enum_trust_dom(hnd->cli, mem_ctx,
697                                                 &hnd->pol, &enum_ctx,
698                                                 num_domains, names, dom_sids);
699         } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) &&  hnd && hnd->cli && hnd->cli->fd == -1);
700
701 done:
702         return result;
703 }
704
705 /* find the domain sid for a domain */
706 static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid)
707 {
708         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
709         TALLOC_CTX *mem_ctx;
710         CLI_POLICY_HND *hnd;
711         fstring level5_dom;
712         int retry;
713
714         DEBUG(3,("rpc: domain_sid\n"));
715
716         if (!(mem_ctx = talloc_init("domain_sid[rpc]")))
717                 return NT_STATUS_NO_MEMORY;
718
719         retry = 0;
720         do {
721                 /* Get sam handle */
722                 if (!(hnd = cm_get_lsa_handle(domain->name)))
723                         goto done;
724
725                 status = cli_lsa_query_info_policy(hnd->cli, mem_ctx,
726                                            &hnd->pol, 0x05, level5_dom, sid);
727         } while (!NT_STATUS_IS_OK(status) && (retry++ < 1) &&  hnd && hnd->cli && hnd->cli->fd == -1);
728
729 done:
730         talloc_destroy(mem_ctx);
731         return status;
732 }
733
734 /* find alternate names list for the domain - none for rpc */
735 static NTSTATUS alternate_name(struct winbindd_domain *domain)
736 {
737         return NT_STATUS_OK;
738 }
739
740
741 /* the rpc backend methods are exposed via this structure */
742 struct winbindd_methods msrpc_methods = {
743         False,
744         query_user_list,
745         enum_dom_groups,
746         enum_local_groups,
747         name_to_sid,
748         sid_to_name,
749         query_user,
750         lookup_usergroups,
751         lookup_groupmem,
752         sequence_number,
753         trusted_domains,
754         domain_sid,
755         alternate_name
756 };