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