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