r4088: Get medieval on our ass about malloc.... :-). Take control of all our allocation
[jra/samba/.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    
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 "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         CLI_POLICY_HND *hnd;
40         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
41         POLICY_HND dom_pol;
42         BOOL got_dom_pol = False;
43         uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
44         unsigned int i, start_idx, retry;
45         uint32 loop_count;
46
47         DEBUG(3,("rpc: query_user_list\n"));
48
49         *num_entries = 0;
50         *info = NULL;
51
52         retry = 0;
53         do {
54                 /* Get sam handle */
55
56                 if ( !NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)) )
57                         return result;
58
59                 /* Get domain handle */
60
61                 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
62                                                 des_access, &domain->sid, &dom_pol);
63
64         } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
65
66         if (!NT_STATUS_IS_OK(result))
67                 goto done;
68
69         got_dom_pol = True;
70
71         i = start_idx = 0;
72         loop_count = 0;
73
74         do {
75                 TALLOC_CTX *ctx2;
76                 uint32 num_dom_users, j;
77                 uint32 max_entries, max_size;
78                 SAM_DISPINFO_CTR ctr;
79                 SAM_DISPINFO_1 info1;
80
81                 ZERO_STRUCT( ctr );
82                 ZERO_STRUCT( info1 );
83                 ctr.sam.info1 = &info1;
84         
85                 if (!(ctx2 = talloc_init("winbindd enum_users"))) {
86                         result = NT_STATUS_NO_MEMORY;
87                         goto done;
88                 }               
89
90                 /* this next bit is copied from net_user_list_internal() */
91
92                 get_query_dispinfo_params( loop_count, &max_entries, &max_size );
93
94                 result = cli_samr_query_dispinfo(hnd->cli, mem_ctx, &dom_pol,
95                         &start_idx, 1, &num_dom_users, max_entries, max_size, &ctr);
96
97                 loop_count++;
98
99                 *num_entries += num_dom_users;
100
101                 *info = TALLOC_REALLOC_ARRAY( mem_ctx, *info, WINBIND_USERINFO, *num_entries);
102
103                 if (!(*info)) {
104                         result = NT_STATUS_NO_MEMORY;
105                         talloc_destroy(ctx2);
106                         goto done;
107                 }
108
109                 for (j = 0; j < num_dom_users; i++, j++) {
110                         fstring username, fullname;
111                         uint32 rid = ctr.sam.info1->sam[j].rid_user;
112                         
113                         unistr2_to_ascii( username, &(&ctr.sam.info1->str[j])->uni_acct_name, sizeof(username)-1);
114                         unistr2_to_ascii( fullname, &(&ctr.sam.info1->str[j])->uni_full_name, sizeof(fullname)-1);
115                         
116                         (*info)[i].acct_name = talloc_strdup(mem_ctx, username );
117                         (*info)[i].full_name = talloc_strdup(mem_ctx, fullname );
118                         (*info)[i].user_sid = rid_to_talloced_sid(domain, mem_ctx, rid );
119                         
120                         /* For the moment we set the primary group for
121                            every user to be the Domain Users group.
122                            There are serious problems with determining
123                            the actual primary group for large domains.
124                            This should really be made into a 'winbind
125                            force group' smb.conf parameter or
126                            something like that. */
127                            
128                         (*info)[i].group_sid = rid_to_talloced_sid(domain, 
129                                 mem_ctx, DOMAIN_GROUP_RID_USERS);
130                 }
131
132                 talloc_destroy(ctx2);
133
134         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
135
136  done:
137
138         if (got_dom_pol)
139                 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
140
141         return result;
142 }
143
144 /* list all domain groups */
145 static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
146                                 TALLOC_CTX *mem_ctx,
147                                 uint32 *num_entries, 
148                                 struct acct_info **info)
149 {
150         uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
151         CLI_POLICY_HND *hnd;
152         POLICY_HND dom_pol;
153         NTSTATUS status;
154         uint32 start = 0;
155         int retry;
156         NTSTATUS result;
157
158         *num_entries = 0;
159         *info = NULL;
160
161         DEBUG(3,("rpc: enum_dom_groups\n"));
162
163         retry = 0;
164         do {
165                 if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)))
166                         return result;
167
168                 status = cli_samr_open_domain(hnd->cli, mem_ctx,
169                                               &hnd->pol, des_access, &domain->sid, &dom_pol);
170         } while (!NT_STATUS_IS_OK(status) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
171
172         if (!NT_STATUS_IS_OK(status))
173                 return status;
174
175         do {
176                 struct acct_info *info2 = NULL;
177                 uint32 count = 0;
178                 TALLOC_CTX *mem_ctx2;
179
180                 mem_ctx2 = talloc_init("enum_dom_groups[rpc]");
181
182                 /* start is updated by this call. */
183                 status = cli_samr_enum_dom_groups(hnd->cli, mem_ctx2, &dom_pol,
184                                                   &start,
185                                                   0xFFFF, /* buffer size? */
186                                                   &info2, &count);
187
188                 if (!NT_STATUS_IS_OK(status) && 
189                     !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
190                         talloc_destroy(mem_ctx2);
191                         break;
192                 }
193
194                 (*info) = TALLOC_REALLOC_ARRAY(mem_ctx, *info, struct acct_info, (*num_entries) + count);
195                 if (! *info) {
196                         talloc_destroy(mem_ctx2);
197                         cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
198                         return NT_STATUS_NO_MEMORY;
199                 }
200
201                 memcpy(&(*info)[*num_entries], info2, count*sizeof(*info2));
202                 (*num_entries) += count;
203                 talloc_destroy(mem_ctx2);
204         } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
205
206         cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
207
208         return status;
209 }
210
211 /* List all domain groups */
212
213 static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
214                                 TALLOC_CTX *mem_ctx,
215                                 uint32 *num_entries, 
216                                 struct acct_info **info)
217 {
218         uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
219         CLI_POLICY_HND *hnd;
220         POLICY_HND dom_pol;
221         NTSTATUS result;
222         int retry;
223
224         *num_entries = 0;
225         *info = NULL;
226
227         retry = 0;
228         do {
229                 if ( !NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)) )
230                         return result;
231
232                 result = cli_samr_open_domain( hnd->cli, mem_ctx, &hnd->pol, 
233                                                 des_access, &domain->sid, &dom_pol);
234         } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
235
236         if ( !NT_STATUS_IS_OK(result))
237                 return result;
238
239         do {
240                 struct acct_info *info2 = NULL;
241                 uint32 count = 0, start = *num_entries;
242                 TALLOC_CTX *mem_ctx2;
243
244                 mem_ctx2 = talloc_init("enum_dom_local_groups[rpc]");
245
246                 result = cli_samr_enum_als_groups( hnd->cli, mem_ctx2, &dom_pol,
247                                           &start, 0xFFFF, &info2, &count);
248                                           
249                 if ( !NT_STATUS_IS_OK(result) 
250                         && !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES) ) 
251                 {
252                         talloc_destroy(mem_ctx2);
253                         break;
254                 }
255
256                 (*info) = TALLOC_REALLOC_ARRAY(mem_ctx, *info, struct acct_info, (*num_entries) + count);
257                 if (! *info) {
258                         talloc_destroy(mem_ctx2);
259                         cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
260                         return NT_STATUS_NO_MEMORY;
261                 }
262
263                 memcpy(&(*info)[*num_entries], info2, count*sizeof(*info2));
264                 (*num_entries) += count;
265                 talloc_destroy(mem_ctx2);
266         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
267
268         cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
269
270         return result;
271 }
272
273 /* convert a single name to a sid in a domain */
274 NTSTATUS msrpc_name_to_sid(struct winbindd_domain *domain,
275                             TALLOC_CTX *mem_ctx,
276                             const char *domain_name,
277                             const char *name,
278                             DOM_SID *sid,
279                             enum SID_NAME_USE *type)
280 {
281         CLI_POLICY_HND *hnd;
282         NTSTATUS result;
283         DOM_SID *sids = NULL;
284         uint32 *types = NULL;
285         const char *full_name;
286         int retry;
287
288         DEBUG(3,("rpc: name_to_sid name=%s\n", name));
289
290         full_name = talloc_asprintf(mem_ctx, "%s\\%s", domain_name, name);
291         
292         if (!full_name) {
293                 DEBUG(0, ("talloc_asprintf failed!\n"));
294                 return NT_STATUS_NO_MEMORY;
295         }
296
297         DEBUG(3,("name_to_sid [rpc] %s for domain %s\n", name, domain_name ));
298
299         retry = 0;
300         do {
301                 if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(domain, &hnd))) {
302                         return result;
303                 }
304         
305                 result = cli_lsa_lookup_names(hnd->cli, mem_ctx, &hnd->pol, 1, 
306                                               &full_name, &sids, &types);
307         } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) &&
308                         hnd && hnd->cli && hnd->cli->fd == -1);
309         
310         /* Return rid and type if lookup successful */
311
312         if (NT_STATUS_IS_OK(result)) {
313                 sid_copy(sid, &sids[0]);
314                 *type = (enum SID_NAME_USE)types[0];
315         }
316
317         return result;
318 }
319
320 /*
321   convert a domain SID to a user or group name
322 */
323 NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain,
324                             TALLOC_CTX *mem_ctx,
325                             const DOM_SID *sid,
326                             char **domain_name,
327                             char **name,
328                             enum SID_NAME_USE *type)
329 {
330         CLI_POLICY_HND *hnd;
331         char **domains;
332         char **names;
333         uint32 *types;
334         NTSTATUS result;
335         int retry;
336
337         DEBUG(3,("sid_to_name [rpc] %s for domain %s\n", sid_string_static(sid),
338                         domain->name ));
339
340         retry = 0;
341         do {
342                 if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(domain, &hnd)))
343                         return result;
344         
345                 result = cli_lsa_lookup_sids(hnd->cli, mem_ctx, &hnd->pol,
346                                              1, sid, &domains, &names, &types);
347         } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) &&
348                         hnd && hnd->cli && hnd->cli->fd == -1);
349
350         if (NT_STATUS_IS_OK(result)) {
351                 *type = (enum SID_NAME_USE)types[0];
352                 *domain_name = domains[0];
353                 *name = names[0];
354                 DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name));
355         }
356
357         return result;
358 }
359
360 /* Lookup user information from a rid or username. */
361 static NTSTATUS query_user(struct winbindd_domain *domain, 
362                            TALLOC_CTX *mem_ctx, 
363                            const DOM_SID *user_sid, 
364                            WINBIND_USERINFO *user_info)
365 {
366         CLI_POLICY_HND *hnd = NULL;
367         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
368         POLICY_HND dom_pol, user_pol;
369         BOOL got_dom_pol = False, got_user_pol = False;
370         SAM_USERINFO_CTR *ctr;
371         int retry;
372         fstring sid_string;
373         uint32 user_rid;
374         NET_USER_INFO_3 *user;
375
376         DEBUG(3,("rpc: query_user rid=%s\n", sid_to_string(sid_string, user_sid)));
377         if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid)) {
378                 goto done;
379         }
380         
381         /* try netsamlogon cache first */
382                         
383         if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL ) 
384         {
385                                 
386                 DEBUG(5,("query_user: Cache lookup succeeded for %s\n", 
387                         sid_string_static(user_sid)));
388                         
389                 user_info->user_sid  = rid_to_talloced_sid( domain, mem_ctx, user_rid );
390                 user_info->group_sid = rid_to_talloced_sid( domain, mem_ctx, user->group_rid );
391                                 
392                 user_info->acct_name = unistr2_tdup(mem_ctx, &user->uni_user_name);
393                 user_info->full_name = unistr2_tdup(mem_ctx, &user->uni_full_name);
394                                                                 
395                 SAFE_FREE(user);
396                                 
397                 return NT_STATUS_OK;
398         }
399         
400         /* no cache; hit the wire */
401                 
402         retry = 0;
403         do {
404                 /* Get sam handle; if we fail here there is no hope */
405                 
406                 if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd))) 
407                         goto done;
408                         
409                 /* Get domain handle */
410
411                 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
412                                               SEC_RIGHTS_MAXIMUM_ALLOWED, 
413                                               &domain->sid, &dom_pol);
414         } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) &&
415                         hnd && hnd->cli && hnd->cli->fd == -1);
416
417         if (!NT_STATUS_IS_OK(result))
418                 goto done;
419
420         got_dom_pol = True;
421
422         /* Get user handle */
423         result = cli_samr_open_user(hnd->cli, mem_ctx, &dom_pol,
424                                     SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid, &user_pol);
425
426         if (!NT_STATUS_IS_OK(result))
427                 goto done;
428
429         got_user_pol = True;
430
431         /* Get user info */
432         result = cli_samr_query_userinfo(hnd->cli, mem_ctx, &user_pol, 
433                                          0x15, &ctr);
434
435         if (!NT_STATUS_IS_OK(result))
436                 goto done;
437
438         cli_samr_close(hnd->cli, mem_ctx, &user_pol);
439         got_user_pol = False;
440
441         user_info->user_sid = rid_to_talloced_sid(domain, mem_ctx, user_rid);
442         user_info->group_sid = rid_to_talloced_sid(domain, mem_ctx, ctr->info.id21->group_rid);
443         user_info->acct_name = unistr2_tdup(mem_ctx, 
444                                             &ctr->info.id21->uni_user_name);
445         user_info->full_name = unistr2_tdup(mem_ctx, 
446                                             &ctr->info.id21->uni_full_name);
447
448  done:
449         /* Clean up policy handles */
450         if (got_user_pol)
451                 cli_samr_close(hnd->cli, mem_ctx, &user_pol);
452
453         if (got_dom_pol)
454                 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
455
456         return result;
457 }                                   
458
459 /* Lookup groups a user is a member of.  I wish Unix had a call like this! */
460 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
461                                   TALLOC_CTX *mem_ctx,
462                                   const DOM_SID *user_sid,
463                                   uint32 *num_groups, DOM_SID ***user_grpsids)
464 {
465         CLI_POLICY_HND *hnd;
466         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
467         POLICY_HND dom_pol, user_pol;
468         uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
469         BOOL got_dom_pol = False, got_user_pol = False;
470         DOM_GID *user_groups;
471         unsigned int i;
472         unsigned int retry;
473         fstring sid_string;
474         uint32 user_rid;
475         NET_USER_INFO_3 *user;
476
477         DEBUG(3,("rpc: lookup_usergroups sid=%s\n", sid_to_string(sid_string, user_sid)));
478
479         *num_groups = 0;
480         *user_grpsids = NULL;
481
482         /* so lets see if we have a cached user_info_3 */
483         
484         if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL )
485         {
486                 DEBUG(5,("query_user: Cache lookup succeeded for %s\n", 
487                         sid_string_static(user_sid)));
488                         
489                 *num_groups = user->num_groups;
490                                 
491                 (*user_grpsids) = TALLOC_ARRAY(mem_ctx, DOM_SID*, *num_groups);
492                 for (i=0;i<(*num_groups);i++) {
493                         (*user_grpsids)[i] = rid_to_talloced_sid(domain, mem_ctx, user->gids[i].g_rid);
494                 }
495                                 
496                 SAFE_FREE(user);
497                                 
498                 return NT_STATUS_OK;
499         }
500
501         /* no cache; hit the wire */
502         
503         retry = 0;
504         do {
505                 /* Get sam handle; if we fail here there is no hope */
506                 
507                 if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)))                 
508                         goto done;
509
510                 /* Get domain handle */
511                 
512                 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
513                                               des_access, &domain->sid, &dom_pol);
514         } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && 
515                         hnd && hnd->cli && hnd->cli->fd == -1);
516
517         if (!NT_STATUS_IS_OK(result))
518                 goto done;
519
520         got_dom_pol = True;
521
522
523         if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid)) {
524                 goto done;
525         }
526
527         /* Get user handle */
528         result = cli_samr_open_user(hnd->cli, mem_ctx, &dom_pol,
529                                         des_access, user_rid, &user_pol);
530
531         if (!NT_STATUS_IS_OK(result))
532                 goto done;
533
534         got_user_pol = True;
535
536         /* Query user rids */
537         result = cli_samr_query_usergroups(hnd->cli, mem_ctx, &user_pol, 
538                                            num_groups, &user_groups);
539
540         if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0)
541                 goto done;
542
543         (*user_grpsids) = TALLOC_ARRAY(mem_ctx, DOM_SID *, *num_groups);
544         if (!(*user_grpsids)) {
545                 result = NT_STATUS_NO_MEMORY;
546                 goto done;
547         }
548
549         for (i=0;i<(*num_groups);i++) {
550                 (*user_grpsids)[i] = rid_to_talloced_sid(domain, mem_ctx, user_groups[i].g_rid);
551         }
552         
553  done:
554         /* Clean up policy handles */
555         if (got_user_pol)
556                 cli_samr_close(hnd->cli, mem_ctx, &user_pol);
557
558         if (got_dom_pol)
559                 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
560
561         return result;
562 }
563
564
565 /* Lookup group membership given a rid.   */
566 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
567                                 TALLOC_CTX *mem_ctx,
568                                 const DOM_SID *group_sid, uint32 *num_names, 
569                                 DOM_SID ***sid_mem, char ***names, 
570                                 uint32 **name_types)
571 {
572         CLI_POLICY_HND *hnd = NULL;
573         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
574         uint32 i, total_names = 0;
575         POLICY_HND dom_pol, group_pol;
576         uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
577         BOOL got_dom_pol = False, got_group_pol = False;
578         uint32 *rid_mem = NULL;
579         uint32 group_rid;
580         int retry;
581         unsigned int j;
582         fstring sid_string;
583
584         DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain->name, sid_to_string(sid_string, group_sid)));
585
586         if (!sid_peek_check_rid(&domain->sid, group_sid, &group_rid)) {
587                 goto done;
588         }
589
590         *num_names = 0;
591
592         retry = 0;
593         do {
594                 /* Get sam handle */
595                 if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)))
596                         goto done;
597
598                 /* Get domain handle */
599
600                 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
601                                 des_access, &domain->sid, &dom_pol);
602         } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
603
604         if (!NT_STATUS_IS_OK(result))
605                 goto done;
606
607         got_dom_pol = True;
608
609         /* Get group handle */
610
611         result = cli_samr_open_group(hnd->cli, mem_ctx, &dom_pol,
612                                      des_access, group_rid, &group_pol);
613
614         if (!NT_STATUS_IS_OK(result))
615                 goto done;
616
617         got_group_pol = True;
618
619         /* Step #1: Get a list of user rids that are the members of the
620            group. */
621
622         result = cli_samr_query_groupmem(hnd->cli, mem_ctx,
623                                          &group_pol, num_names, &rid_mem,
624                                          name_types);
625
626         if (!NT_STATUS_IS_OK(result))
627                 goto done;
628
629         if (!*num_names) {
630                 names = NULL;
631                 name_types = NULL;
632                 sid_mem = NULL;
633                 goto done;
634         }
635
636         /* Step #2: Convert list of rids into list of usernames.  Do this
637            in bunches of ~1000 to avoid crashing NT4.  It looks like there
638            is a buffer overflow or something like that lurking around
639            somewhere. */
640
641 #define MAX_LOOKUP_RIDS 900
642
643         *names = TALLOC_ZERO_ARRAY(mem_ctx, char *, *num_names);
644         *name_types = TALLOC_ZERO_ARRAY(mem_ctx, uint32, *num_names);
645         *sid_mem = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID *, *num_names);
646
647         for (j=0;j<(*num_names);j++) {
648                 (*sid_mem)[j] = rid_to_talloced_sid(domain, mem_ctx, (rid_mem)[j]);
649         }
650         
651         if (*num_names>0 && (!*names || !*name_types)) {
652                 result = NT_STATUS_NO_MEMORY;
653                 goto done;
654         }
655
656         for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) {
657                 int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS);
658                 uint32 tmp_num_names = 0;
659                 char **tmp_names = NULL;
660                 uint32 *tmp_types = NULL;
661
662                 /* Lookup a chunk of rids */
663
664                 result = cli_samr_lookup_rids(hnd->cli, mem_ctx,
665                                               &dom_pol, 1000, /* flags */
666                                               num_lookup_rids,
667                                               &rid_mem[i],
668                                               &tmp_num_names,
669                                               &tmp_names, &tmp_types);
670
671                 /* see if we have a real error (and yes the STATUS_SOME_UNMAPPED is
672                    the one returned from 2k) */
673                 
674                 if (!NT_STATUS_IS_OK(result) && NT_STATUS_V(result) != NT_STATUS_V(STATUS_SOME_UNMAPPED))
675                         goto done;
676                         
677                 /* Copy result into array.  The talloc system will take
678                    care of freeing the temporary arrays later on. */
679
680                 memcpy(&(*names)[i], tmp_names, sizeof(char *) * 
681                        tmp_num_names);
682
683                 memcpy(&(*name_types)[i], tmp_types, sizeof(uint32) *
684                        tmp_num_names);
685                 
686                 total_names += tmp_num_names;
687         }
688
689         *num_names = total_names;
690
691         result = NT_STATUS_OK;
692         
693 done:
694         if (got_group_pol)
695                 cli_samr_close(hnd->cli, mem_ctx, &group_pol);
696
697         if (got_dom_pol)
698                 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
699
700         return result;
701 }
702
703 #ifdef HAVE_LDAP
704
705 #include <ldap.h>
706
707 static int get_ldap_seq(const char *server, int port, uint32 *seq)
708 {
709         int ret = -1;
710         struct timeval to;
711         char *attrs[] = {"highestCommittedUSN", NULL};
712         LDAPMessage *res = NULL;
713         char **values = NULL;
714         LDAP *ldp = NULL;
715
716         *seq = DOM_SEQUENCE_NONE;
717
718         /*
719          * Parameterised (5) second timeout on open. This is needed as the search timeout
720          * doesn't seem to apply to doing an open as well. JRA.
721          */
722
723         if ((ldp = ldap_open_with_timeout(server, port, lp_ldap_timeout())) == NULL)
724                 return -1;
725
726         /* Timeout if no response within 20 seconds. */
727         to.tv_sec = 10;
728         to.tv_usec = 0;
729
730         if (ldap_search_st(ldp, "", LDAP_SCOPE_BASE, "(objectclass=*)", &attrs[0], 0, &to, &res))
731                 goto done;
732
733         if (ldap_count_entries(ldp, res) != 1)
734                 goto done;
735
736         values = ldap_get_values(ldp, res, "highestCommittedUSN");
737         if (!values || !values[0])
738                 goto done;
739
740         *seq = atoi(values[0]);
741         ret = 0;
742
743   done:
744
745         if (values)
746                 ldap_value_free(values);
747         if (res)
748                 ldap_msgfree(res);
749         if (ldp)
750                 ldap_unbind(ldp);
751         return ret;
752 }
753
754 /**********************************************************************
755  Get the sequence number for a Windows AD native mode domain using
756  LDAP queries
757 **********************************************************************/
758
759 static int get_ldap_sequence_number( const char* domain, uint32 *seq)
760 {
761         int ret = -1;
762         int i, port = LDAP_PORT;
763         struct ip_service *ip_list = NULL;
764         int count;
765         
766         if ( !get_sorted_dc_list(domain, &ip_list, &count, False) ) {
767                 DEBUG(3, ("Could not look up dc's for domain %s\n", domain));
768                 return False;
769         }
770
771         /* Finally return first DC that we can contact */
772
773         for (i = 0; i < count; i++) {
774                 fstring ipstr;
775
776                 /* since the is an LDAP lookup, default to the LDAP_PORT is not set */
777                 port = (ip_list[i].port!= PORT_NONE) ? ip_list[i].port : LDAP_PORT;
778
779                 fstrcpy( ipstr, inet_ntoa(ip_list[i].ip) );
780                 
781                 if (is_zero_ip(ip_list[i].ip))
782                         continue;
783
784                 if ( (ret = get_ldap_seq( ipstr, port,  seq)) == 0 )
785                         goto done;
786
787                 /* add to failed connection cache */
788                 add_failed_connection_entry( domain, ipstr, NT_STATUS_UNSUCCESSFUL );
789         }
790
791 done:
792         if ( ret == 0 ) {
793                 DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence number for Domain (%s) from DC (%s:%d)\n", 
794                         domain, inet_ntoa(ip_list[i].ip), port));
795         }
796
797         SAFE_FREE(ip_list);
798
799         return ret;
800 }
801
802 #endif /* HAVE_LDAP */
803
804 /* find the sequence number for a domain */
805 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
806 {
807         TALLOC_CTX *mem_ctx;
808         CLI_POLICY_HND *hnd;
809         SAM_UNK_CTR ctr;
810         uint16 switch_value = 2;
811         NTSTATUS result;
812         POLICY_HND dom_pol;
813         BOOL got_dom_pol = False;
814         uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
815         int retry;
816
817         DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name));
818
819         *seq = DOM_SEQUENCE_NONE;
820
821         if (!(mem_ctx = talloc_init("sequence_number[rpc]")))
822                 return NT_STATUS_NO_MEMORY;
823
824         retry = 0;
825         do {
826 #ifdef HAVE_LDAP
827                 if ( domain->native_mode ) 
828                 {
829                         DEBUG(8,("using get_ldap_seq() to retrieve the sequence number\n"));
830
831                         if ( get_ldap_sequence_number( domain->name, seq ) == 0 ) {                     
832                                 result = NT_STATUS_OK;
833                                 DEBUG(10,("domain_sequence_number: LDAP for domain %s is %u\n",
834                                         domain->name, *seq));
835                                 goto done;
836                         }
837
838                         DEBUG(10,("domain_sequence_number: failed to get LDAP sequence number for domain %s\n",
839                         domain->name ));
840                 }
841 #endif /* HAVE_LDAP */
842                 /* Get sam handle */
843                 if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)))
844                         goto done;
845
846                 /* Get domain handle */
847                 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol, 
848                                       des_access, &domain->sid, &dom_pol);
849         } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
850
851         if (!NT_STATUS_IS_OK(result))
852                 goto done;
853
854         got_dom_pol = True;
855
856         /* Query domain info */
857
858         result = cli_samr_query_dom_info(hnd->cli, mem_ctx, &dom_pol,
859                                          switch_value, &ctr);
860
861         if (NT_STATUS_IS_OK(result)) {
862                 *seq = ctr.info.inf2.seq_num;
863                 DEBUG(10,("domain_sequence_number: for domain %s is %u\n", domain->name, (unsigned)*seq));
864         } else {
865                 DEBUG(10,("domain_sequence_number: failed to get sequence number (%u) for domain %s\n",
866                         (unsigned)*seq, domain->name ));
867         }
868
869   done:
870
871         if (got_dom_pol)
872                 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
873
874         talloc_destroy(mem_ctx);
875
876         return result;
877 }
878
879 /* get a list of trusted domains */
880 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
881                                 TALLOC_CTX *mem_ctx,
882                                 uint32 *num_domains,
883                                 char ***names,
884                                 char ***alt_names,
885                                 DOM_SID **dom_sids)
886 {
887         CLI_POLICY_HND *hnd;
888         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
889         uint32 enum_ctx = 0;
890         int retry;
891
892         DEBUG(3,("rpc: trusted_domains\n"));
893
894         *num_domains = 0;
895         *alt_names = NULL;
896
897         retry = 0;
898         do {
899                 if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(find_our_domain(), &hnd)))
900                         goto done;
901
902                 result = cli_lsa_enum_trust_dom(hnd->cli, mem_ctx,
903                                                 &hnd->pol, &enum_ctx,
904                                                 num_domains, names, dom_sids);
905         } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) &&  hnd && hnd->cli && hnd->cli->fd == -1);
906
907 done:
908         return result;
909 }
910
911 /* find the domain sid for a domain */
912 static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid)
913 {
914         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
915         TALLOC_CTX *mem_ctx;
916         CLI_POLICY_HND *hnd;
917         char *level5_dom;
918         DOM_SID *alloc_sid;
919         int retry;
920
921         DEBUG(3,("rpc: domain_sid\n"));
922
923         if (!(mem_ctx = talloc_init("domain_sid[rpc]")))
924                 return NT_STATUS_NO_MEMORY;
925
926         retry = 0;
927         do {
928                 /* Get lsa handle */
929                 if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(domain, &hnd)))
930                         goto done;
931
932                 result = cli_lsa_query_info_policy(hnd->cli, mem_ctx,
933                                            &hnd->pol, 0x05, &level5_dom, &alloc_sid);
934         } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) &&  hnd && hnd->cli && hnd->cli->fd == -1);
935
936         if (NT_STATUS_IS_OK(result)) {
937                 if (alloc_sid) {
938                         sid_copy(sid, alloc_sid);
939                 } else {
940                         result = NT_STATUS_NO_MEMORY;
941                 }
942         }
943
944 done:
945         talloc_destroy(mem_ctx);
946         return result;
947 }
948
949 /* find alternate names list for the domain - none for rpc */
950 static NTSTATUS alternate_name(struct winbindd_domain *domain)
951 {
952         return NT_STATUS_OK;
953 }
954
955
956 /* the rpc backend methods are exposed via this structure */
957 struct winbindd_methods msrpc_methods = {
958         False,
959         query_user_list,
960         enum_dom_groups,
961         enum_local_groups,
962         msrpc_name_to_sid,
963         msrpc_sid_to_name,
964         query_user,
965         lookup_usergroups,
966         lookup_groupmem,
967         sequence_number,
968         trusted_domains,
969         domain_sid,
970         alternate_name
971 };