r6149: Fixes bugs #2498 and 2484.
[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    Copyright (C) Volker Lendecke 2005
9    
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25 #include "includes.h"
26 #include "winbindd.h"
27
28 #undef DBGC_CLASS
29 #define DBGC_CLASS DBGC_WINBIND
30
31
32 /* Query display info for a domain.  This returns enough information plus a
33    bit extra to give an overview of domain users for the User Manager
34    application. */
35 static NTSTATUS query_user_list(struct winbindd_domain *domain,
36                                TALLOC_CTX *mem_ctx,
37                                uint32 *num_entries, 
38                                WINBIND_USERINFO **info)
39 {
40         CLI_POLICY_HND *hnd;
41         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
42         POLICY_HND dom_pol;
43         BOOL got_dom_pol = False;
44         uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
45         unsigned int i, start_idx, retry;
46         uint32 loop_count;
47
48         DEBUG(3,("rpc: query_user_list\n"));
49
50         *num_entries = 0;
51         *info = NULL;
52
53         retry = 0;
54         do {
55                 /* Get sam handle */
56
57                 if ( !NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)) )
58                         return result;
59
60                 /* Get domain handle */
61
62                 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
63                                                 des_access, &domain->sid, &dom_pol);
64
65         } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
66
67         if (!NT_STATUS_IS_OK(result))
68                 goto done;
69
70         got_dom_pol = True;
71
72         i = start_idx = 0;
73         loop_count = 0;
74
75         do {
76                 TALLOC_CTX *ctx2;
77                 uint32 num_dom_users, j;
78                 uint32 max_entries, max_size;
79                 SAM_DISPINFO_CTR ctr;
80                 SAM_DISPINFO_1 info1;
81
82                 ZERO_STRUCT( ctr );
83                 ZERO_STRUCT( info1 );
84                 ctr.sam.info1 = &info1;
85         
86                 if (!(ctx2 = talloc_init("winbindd enum_users"))) {
87                         result = NT_STATUS_NO_MEMORY;
88                         goto done;
89                 }               
90
91                 /* this next bit is copied from net_user_list_internal() */
92
93                 get_query_dispinfo_params( loop_count, &max_entries, &max_size );
94
95                 result = cli_samr_query_dispinfo(hnd->cli, mem_ctx, &dom_pol,
96                         &start_idx, 1, &num_dom_users, max_entries, max_size, &ctr);
97
98                 loop_count++;
99
100                 *num_entries += num_dom_users;
101
102                 *info = TALLOC_REALLOC_ARRAY( mem_ctx, *info, WINBIND_USERINFO, *num_entries);
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, &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_ARRAY(mem_ctx, *info, struct acct_info, (*num_entries) + count);
196                 if (! *info) {
197                         talloc_destroy(mem_ctx2);
198                         cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
199                         return NT_STATUS_NO_MEMORY;
200                 }
201
202                 memcpy(&(*info)[*num_entries], info2, count*sizeof(*info2));
203                 (*num_entries) += count;
204                 talloc_destroy(mem_ctx2);
205         } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
206
207         cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
208
209         return status;
210 }
211
212 /* List all domain groups */
213
214 static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
215                                 TALLOC_CTX *mem_ctx,
216                                 uint32 *num_entries, 
217                                 struct acct_info **info)
218 {
219         uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
220         CLI_POLICY_HND *hnd;
221         POLICY_HND dom_pol;
222         NTSTATUS result;
223         int retry;
224
225         *num_entries = 0;
226         *info = NULL;
227
228         retry = 0;
229         do {
230                 if ( !NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)) )
231                         return result;
232
233                 result = cli_samr_open_domain( hnd->cli, mem_ctx, &hnd->pol, 
234                                                 des_access, &domain->sid, &dom_pol);
235         } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
236
237         if ( !NT_STATUS_IS_OK(result))
238                 return result;
239
240         do {
241                 struct acct_info *info2 = NULL;
242                 uint32 count = 0, start = *num_entries;
243                 TALLOC_CTX *mem_ctx2;
244
245                 mem_ctx2 = talloc_init("enum_dom_local_groups[rpc]");
246
247                 result = cli_samr_enum_als_groups( hnd->cli, mem_ctx2, &dom_pol,
248                                           &start, 0xFFFF, &info2, &count);
249                                           
250                 if ( !NT_STATUS_IS_OK(result) 
251                         && !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES) ) 
252                 {
253                         talloc_destroy(mem_ctx2);
254                         break;
255                 }
256
257                 (*info) = TALLOC_REALLOC_ARRAY(mem_ctx, *info, struct acct_info, (*num_entries) + count);
258                 if (! *info) {
259                         talloc_destroy(mem_ctx2);
260                         cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
261                         return NT_STATUS_NO_MEMORY;
262                 }
263
264                 memcpy(&(*info)[*num_entries], info2, count*sizeof(*info2));
265                 (*num_entries) += count;
266                 talloc_destroy(mem_ctx2);
267         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
268
269         cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
270
271         return result;
272 }
273
274 /* convert a single name to a sid in a domain */
275 NTSTATUS msrpc_name_to_sid(struct winbindd_domain *domain,
276                             TALLOC_CTX *mem_ctx,
277                             const char *domain_name,
278                             const char *name,
279                             DOM_SID *sid,
280                             enum SID_NAME_USE *type)
281 {
282         CLI_POLICY_HND *hnd;
283         NTSTATUS result;
284         DOM_SID *sids = NULL;
285         uint32 *types = NULL;
286         const char *full_name;
287         int retry;
288
289         DEBUG(3,("rpc: name_to_sid name=%s\n", name));
290
291         full_name = talloc_asprintf(mem_ctx, "%s\\%s", domain_name, name);
292         
293         if (!full_name) {
294                 DEBUG(0, ("talloc_asprintf failed!\n"));
295                 return NT_STATUS_NO_MEMORY;
296         }
297
298         DEBUG(3,("name_to_sid [rpc] %s for domain %s\n", name, domain_name ));
299
300         retry = 0;
301         do {
302                 if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(domain, &hnd))) {
303                         return result;
304                 }
305         
306                 result = cli_lsa_lookup_names(hnd->cli, mem_ctx, &hnd->pol, 1, 
307                                               &full_name, &sids, &types);
308         } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) &&
309                         hnd && hnd->cli && hnd->cli->fd == -1);
310         
311         /* Return rid and type if lookup successful */
312
313         if (NT_STATUS_IS_OK(result)) {
314                 sid_copy(sid, &sids[0]);
315                 *type = (enum SID_NAME_USE)types[0];
316         }
317
318         return result;
319 }
320
321 /*
322   convert a domain SID to a user or group name
323 */
324 NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain,
325                             TALLOC_CTX *mem_ctx,
326                             const DOM_SID *sid,
327                             char **domain_name,
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, &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                 *domain_name = domains[0];
354                 *name = names[0];
355                 DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name));
356         }
357
358         return result;
359 }
360
361 /* Lookup user information from a rid or username. */
362 static NTSTATUS query_user(struct winbindd_domain *domain, 
363                            TALLOC_CTX *mem_ctx, 
364                            const DOM_SID *user_sid, 
365                            WINBIND_USERINFO *user_info)
366 {
367         CLI_POLICY_HND *hnd = NULL;
368         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
369         POLICY_HND dom_pol, user_pol;
370         BOOL got_dom_pol = False, got_user_pol = False;
371         SAM_USERINFO_CTR *ctr;
372         int retry;
373         fstring sid_string;
374         uint32 user_rid;
375         NET_USER_INFO_3 *user;
376
377         DEBUG(3,("rpc: query_user rid=%s\n", sid_to_string(sid_string, user_sid)));
378         if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid)) {
379                 goto done;
380         }
381         
382         /* try netsamlogon cache first */
383                         
384         if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL ) 
385         {
386                                 
387                 DEBUG(5,("query_user: Cache lookup succeeded for %s\n", 
388                         sid_string_static(user_sid)));
389                         
390                 user_info->user_sid  = rid_to_talloced_sid( domain, mem_ctx, user_rid );
391                 user_info->group_sid = rid_to_talloced_sid( domain, mem_ctx, user->group_rid );
392                                 
393                 user_info->acct_name = unistr2_tdup(mem_ctx, &user->uni_user_name);
394                 user_info->full_name = unistr2_tdup(mem_ctx, &user->uni_full_name);
395                                                                 
396                 SAFE_FREE(user);
397                                 
398                 return NT_STATUS_OK;
399         }
400         
401         /* no cache; hit the wire */
402                 
403         retry = 0;
404         do {
405                 /* Get sam handle; if we fail here there is no hope */
406                 
407                 if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd))) 
408                         goto done;
409                         
410                 /* Get domain handle */
411
412                 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
413                                               SEC_RIGHTS_MAXIMUM_ALLOWED, 
414                                               &domain->sid, &dom_pol);
415         } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) &&
416                         hnd && hnd->cli && hnd->cli->fd == -1);
417
418         if (!NT_STATUS_IS_OK(result))
419                 goto done;
420
421         got_dom_pol = True;
422
423         /* Get user handle */
424         result = cli_samr_open_user(hnd->cli, mem_ctx, &dom_pol,
425                                     SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid, &user_pol);
426
427         if (!NT_STATUS_IS_OK(result))
428                 goto done;
429
430         got_user_pol = True;
431
432         /* Get user info */
433         result = cli_samr_query_userinfo(hnd->cli, mem_ctx, &user_pol, 
434                                          0x15, &ctr);
435
436         if (!NT_STATUS_IS_OK(result))
437                 goto done;
438
439         cli_samr_close(hnd->cli, mem_ctx, &user_pol);
440         got_user_pol = False;
441
442         user_info->user_sid = rid_to_talloced_sid(domain, mem_ctx, user_rid);
443         user_info->group_sid = rid_to_talloced_sid(domain, mem_ctx, ctr->info.id21->group_rid);
444         user_info->acct_name = unistr2_tdup(mem_ctx, 
445                                             &ctr->info.id21->uni_user_name);
446         user_info->full_name = unistr2_tdup(mem_ctx, 
447                                             &ctr->info.id21->uni_full_name);
448
449  done:
450         /* Clean up policy handles */
451         if (got_user_pol)
452                 cli_samr_close(hnd->cli, mem_ctx, &user_pol);
453
454         if (got_dom_pol)
455                 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
456
457         return result;
458 }                                   
459
460 /* Lookup groups a user is a member of.  I wish Unix had a call like this! */
461 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
462                                   TALLOC_CTX *mem_ctx,
463                                   const DOM_SID *user_sid,
464                                   uint32 *num_groups, DOM_SID ***user_grpsids)
465 {
466         CLI_POLICY_HND *hnd;
467         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
468         POLICY_HND dom_pol, user_pol;
469         uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
470         BOOL got_dom_pol = False, got_user_pol = False;
471         DOM_GID *user_groups;
472         unsigned int i;
473         unsigned int retry;
474         fstring sid_string;
475         uint32 user_rid;
476         NET_USER_INFO_3 *user;
477
478         DEBUG(3,("rpc: lookup_usergroups sid=%s\n", sid_to_string(sid_string, user_sid)));
479
480         *num_groups = 0;
481         *user_grpsids = NULL;
482
483         /* so lets see if we have a cached user_info_3 */
484         
485         if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL )
486         {
487                 DEBUG(5,("query_user: Cache lookup succeeded for %s\n", 
488                         sid_string_static(user_sid)));
489                         
490                 *num_groups = user->num_groups;
491                                 
492                 (*user_grpsids) = TALLOC_ARRAY(mem_ctx, DOM_SID*, *num_groups);
493                 for (i=0;i<(*num_groups);i++) {
494                         (*user_grpsids)[i] = rid_to_talloced_sid(domain, mem_ctx, user->gids[i].g_rid);
495                 }
496                                 
497                 SAFE_FREE(user);
498                                 
499                 return NT_STATUS_OK;
500         }
501
502         /* no cache; hit the wire */
503         
504         retry = 0;
505         do {
506                 /* Get sam handle; if we fail here there is no hope */
507                 
508                 if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)))                 
509                         goto done;
510
511                 /* Get domain handle */
512                 
513                 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
514                                               des_access, &domain->sid, &dom_pol);
515         } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && 
516                         hnd && hnd->cli && hnd->cli->fd == -1);
517
518         if (!NT_STATUS_IS_OK(result))
519                 goto done;
520
521         got_dom_pol = True;
522
523
524         if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid)) {
525                 goto done;
526         }
527
528         /* Get user handle */
529         result = cli_samr_open_user(hnd->cli, mem_ctx, &dom_pol,
530                                         des_access, user_rid, &user_pol);
531
532         if (!NT_STATUS_IS_OK(result))
533                 goto done;
534
535         got_user_pol = True;
536
537         /* Query user rids */
538         result = cli_samr_query_usergroups(hnd->cli, mem_ctx, &user_pol, 
539                                            num_groups, &user_groups);
540
541         if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0)
542                 goto done;
543
544         (*user_grpsids) = TALLOC_ARRAY(mem_ctx, DOM_SID *, *num_groups);
545         if (!(*user_grpsids)) {
546                 result = NT_STATUS_NO_MEMORY;
547                 goto done;
548         }
549
550         for (i=0;i<(*num_groups);i++) {
551                 (*user_grpsids)[i] = rid_to_talloced_sid(domain, mem_ctx, user_groups[i].g_rid);
552         }
553         
554  done:
555         /* Clean up policy handles */
556         if (got_user_pol)
557                 cli_samr_close(hnd->cli, mem_ctx, &user_pol);
558
559         if (got_dom_pol)
560                 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
561
562         return result;
563 }
564
565 NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain,
566                                   TALLOC_CTX *mem_ctx,
567                                   uint32 num_sids, DOM_SID **sids,
568                                   uint32 *num_aliases, uint32 **alias_rids)
569 {
570         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
571         CLI_POLICY_HND *hnd;
572         BOOL got_dom_pol = False;
573         POLICY_HND dom_pol;
574         DOM_SID2 *sid2;
575         int i, retry;
576
577         *num_aliases = 0;
578         *alias_rids = NULL;
579
580         retry = 0;
581         do {
582                 /* Get sam handle; if we fail here there is no hope */
583                 
584                 if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain,
585                                                                 &hnd)))
586                         goto done;
587
588                 /* Get domain handle */
589                 
590                 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
591                                               SEC_RIGHTS_MAXIMUM_ALLOWED,
592                                               &domain->sid, &dom_pol);
593         } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && 
594                         hnd && hnd->cli && hnd->cli->fd == -1);
595
596         if (!NT_STATUS_IS_OK(result))
597                 goto done;
598
599         got_dom_pol = True;
600
601         sid2 = TALLOC_ARRAY(mem_ctx, DOM_SID2, num_sids);
602
603         if (sid2 == NULL) {
604                 result = NT_STATUS_NO_MEMORY;
605                 goto done;
606         }
607
608         for (i=0; i<num_sids; i++) {
609                 sid_copy(&sid2[i].sid, sids[i]);
610                 sid2[i].num_auths = sid2[i].sid.num_auths;
611         }
612
613         result = cli_samr_query_useraliases(hnd->cli, mem_ctx, &dom_pol,
614                                             num_sids, sid2,
615                                             num_aliases, alias_rids);
616
617  done:
618
619         if (got_dom_pol)
620                 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
621         
622         return result;
623 }
624
625
626 /* Lookup group membership given a rid.   */
627 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
628                                 TALLOC_CTX *mem_ctx,
629                                 const DOM_SID *group_sid, uint32 *num_names, 
630                                 DOM_SID ***sid_mem, char ***names, 
631                                 uint32 **name_types)
632 {
633         CLI_POLICY_HND *hnd = NULL;
634         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
635         uint32 i, total_names = 0;
636         POLICY_HND dom_pol, group_pol;
637         uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
638         BOOL got_dom_pol = False, got_group_pol = False;
639         uint32 *rid_mem = NULL;
640         uint32 group_rid;
641         int retry;
642         unsigned int j;
643         fstring sid_string;
644
645         DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain->name, sid_to_string(sid_string, group_sid)));
646
647         if (!sid_peek_check_rid(&domain->sid, group_sid, &group_rid)) {
648                 goto done;
649         }
650
651         *num_names = 0;
652
653         retry = 0;
654         do {
655                 /* Get sam handle */
656                 if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)))
657                         goto done;
658
659                 /* Get domain handle */
660
661                 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
662                                 des_access, &domain->sid, &dom_pol);
663         } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
664
665         if (!NT_STATUS_IS_OK(result))
666                 goto done;
667
668         got_dom_pol = True;
669
670         /* Get group handle */
671
672         result = cli_samr_open_group(hnd->cli, mem_ctx, &dom_pol,
673                                      des_access, group_rid, &group_pol);
674
675         if (!NT_STATUS_IS_OK(result))
676                 goto done;
677
678         got_group_pol = True;
679
680         /* Step #1: Get a list of user rids that are the members of the
681            group. */
682
683         result = cli_samr_query_groupmem(hnd->cli, mem_ctx,
684                                          &group_pol, num_names, &rid_mem,
685                                          name_types);
686
687         if (!NT_STATUS_IS_OK(result))
688                 goto done;
689
690         if (!*num_names) {
691                 names = NULL;
692                 name_types = NULL;
693                 sid_mem = NULL;
694                 goto done;
695         }
696
697         /* Step #2: Convert list of rids into list of usernames.  Do this
698            in bunches of ~1000 to avoid crashing NT4.  It looks like there
699            is a buffer overflow or something like that lurking around
700            somewhere. */
701
702 #define MAX_LOOKUP_RIDS 900
703
704         *names = TALLOC_ZERO_ARRAY(mem_ctx, char *, *num_names);
705         *name_types = TALLOC_ZERO_ARRAY(mem_ctx, uint32, *num_names);
706         *sid_mem = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID *, *num_names);
707
708         for (j=0;j<(*num_names);j++) {
709                 (*sid_mem)[j] = rid_to_talloced_sid(domain, mem_ctx, (rid_mem)[j]);
710         }
711         
712         if (*num_names>0 && (!*names || !*name_types)) {
713                 result = NT_STATUS_NO_MEMORY;
714                 goto done;
715         }
716
717         for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) {
718                 int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS);
719                 uint32 tmp_num_names = 0;
720                 char **tmp_names = NULL;
721                 uint32 *tmp_types = NULL;
722
723                 /* Lookup a chunk of rids */
724
725                 result = cli_samr_lookup_rids(hnd->cli, mem_ctx,
726                                               &dom_pol,
727                                               num_lookup_rids,
728                                               &rid_mem[i],
729                                               &tmp_num_names,
730                                               &tmp_names, &tmp_types);
731
732                 /* see if we have a real error (and yes the STATUS_SOME_UNMAPPED is
733                    the one returned from 2k) */
734                 
735                 if (!NT_STATUS_IS_OK(result) && NT_STATUS_V(result) != NT_STATUS_V(STATUS_SOME_UNMAPPED))
736                         goto done;
737                         
738                 /* Copy result into array.  The talloc system will take
739                    care of freeing the temporary arrays later on. */
740
741                 memcpy(&(*names)[i], tmp_names, sizeof(char *) * 
742                        tmp_num_names);
743
744                 memcpy(&(*name_types)[i], tmp_types, sizeof(uint32) *
745                        tmp_num_names);
746                 
747                 total_names += tmp_num_names;
748         }
749
750         *num_names = total_names;
751
752         result = NT_STATUS_OK;
753         
754 done:
755         if (got_group_pol)
756                 cli_samr_close(hnd->cli, mem_ctx, &group_pol);
757
758         if (got_dom_pol)
759                 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
760
761         return result;
762 }
763
764 #ifdef HAVE_LDAP
765
766 #include <ldap.h>
767
768 static int get_ldap_seq(const char *server, int port, uint32 *seq)
769 {
770         int ret = -1;
771         struct timeval to;
772         const char *attrs[] = {"highestCommittedUSN", NULL};
773         LDAPMessage *res = NULL;
774         char **values = NULL;
775         LDAP *ldp = NULL;
776
777         *seq = DOM_SEQUENCE_NONE;
778
779         /*
780          * Parameterised (5) second timeout on open. This is needed as the search timeout
781          * doesn't seem to apply to doing an open as well. JRA.
782          */
783
784         if ((ldp = ldap_open_with_timeout(server, port, lp_ldap_timeout())) == NULL)
785                 return -1;
786
787         /* Timeout if no response within 20 seconds. */
788         to.tv_sec = 10;
789         to.tv_usec = 0;
790
791         if (ldap_search_st(ldp, "", LDAP_SCOPE_BASE, "(objectclass=*)",
792                            CONST_DISCARD(char **, &attrs[0]), 0, &to, &res))
793                 goto done;
794
795         if (ldap_count_entries(ldp, res) != 1)
796                 goto done;
797
798         values = ldap_get_values(ldp, res, "highestCommittedUSN");
799         if (!values || !values[0])
800                 goto done;
801
802         *seq = atoi(values[0]);
803         ret = 0;
804
805   done:
806
807         if (values)
808                 ldap_value_free(values);
809         if (res)
810                 ldap_msgfree(res);
811         if (ldp)
812                 ldap_unbind(ldp);
813         return ret;
814 }
815
816 /**********************************************************************
817  Get the sequence number for a Windows AD native mode domain using
818  LDAP queries
819 **********************************************************************/
820
821 static int get_ldap_sequence_number( const char* domain, uint32 *seq)
822 {
823         int ret = -1;
824         int i, port = LDAP_PORT;
825         struct ip_service *ip_list = NULL;
826         int count;
827         
828         if ( !get_sorted_dc_list(domain, &ip_list, &count, False) ) {
829                 DEBUG(3, ("Could not look up dc's for domain %s\n", domain));
830                 return False;
831         }
832
833         /* Finally return first DC that we can contact */
834
835         for (i = 0; i < count; i++) {
836                 fstring ipstr;
837
838                 /* since the is an LDAP lookup, default to the LDAP_PORT is not set */
839                 port = (ip_list[i].port!= PORT_NONE) ? ip_list[i].port : LDAP_PORT;
840
841                 fstrcpy( ipstr, inet_ntoa(ip_list[i].ip) );
842                 
843                 if (is_zero_ip(ip_list[i].ip))
844                         continue;
845
846                 if ( (ret = get_ldap_seq( ipstr, port,  seq)) == 0 )
847                         goto done;
848
849                 /* add to failed connection cache */
850                 add_failed_connection_entry( domain, ipstr, NT_STATUS_UNSUCCESSFUL );
851         }
852
853 done:
854         if ( ret == 0 ) {
855                 DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence number for Domain (%s) from DC (%s:%d)\n", 
856                         domain, inet_ntoa(ip_list[i].ip), port));
857         }
858
859         SAFE_FREE(ip_list);
860
861         return ret;
862 }
863
864 #endif /* HAVE_LDAP */
865
866 /* find the sequence number for a domain */
867 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
868 {
869         TALLOC_CTX *mem_ctx;
870         CLI_POLICY_HND *hnd;
871         SAM_UNK_CTR ctr;
872         NTSTATUS result;
873         POLICY_HND dom_pol;
874         BOOL got_dom_pol = False;
875         BOOL got_seq_num = False;
876         uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
877         int retry;
878
879         DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name));
880
881         *seq = DOM_SEQUENCE_NONE;
882
883         if (!(mem_ctx = talloc_init("sequence_number[rpc]")))
884                 return NT_STATUS_NO_MEMORY;
885
886         retry = 0;
887         do {
888 #ifdef HAVE_LDAP
889                 if ( domain->native_mode ) 
890                 {
891                         DEBUG(8,("using get_ldap_seq() to retrieve the sequence number\n"));
892
893                         if ( get_ldap_sequence_number( domain->name, seq ) == 0 ) {                     
894                                 result = NT_STATUS_OK;
895                                 DEBUG(10,("domain_sequence_number: LDAP for domain %s is %u\n",
896                                         domain->name, *seq));
897                                 goto done;
898                         }
899
900                         DEBUG(10,("domain_sequence_number: failed to get LDAP sequence number for domain %s\n",
901                         domain->name ));
902                 }
903 #endif /* HAVE_LDAP */
904                 /* Get sam handle */
905                 if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)))
906                         goto done;
907
908                 /* Get domain handle */
909                 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol, 
910                                       des_access, &domain->sid, &dom_pol);
911         } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
912
913         if (!NT_STATUS_IS_OK(result))
914                 goto done;
915
916         got_dom_pol = True;
917
918         /* Query domain info */
919
920         result = cli_samr_query_dom_info(hnd->cli, mem_ctx, &dom_pol,
921                                          8, &ctr);
922
923         if (NT_STATUS_IS_OK(result)) {
924                 *seq = ctr.info.inf8.seq_num.low;
925                 got_seq_num = True;
926                 goto seq_num;
927         }
928
929         /* retry with info-level 2 in case the dc does not support info-level 8
930          * (like all older samba2 and samba3 dc's - Guenther */
931
932         result = cli_samr_query_dom_info(hnd->cli, mem_ctx, &dom_pol,
933                                          2, &ctr);
934         
935         if (NT_STATUS_IS_OK(result)) {
936                 *seq = ctr.info.inf2.seq_num.low;
937                 got_seq_num = True;
938         }
939
940  seq_num:
941         if (got_seq_num) {
942                 DEBUG(10,("domain_sequence_number: for domain %s is %u\n", domain->name, (unsigned)*seq));
943         } else {
944                 DEBUG(10,("domain_sequence_number: failed to get sequence number (%u) for domain %s\n",
945                         (unsigned)*seq, domain->name ));
946         }
947
948   done:
949
950         if (got_dom_pol)
951                 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
952
953         talloc_destroy(mem_ctx);
954
955         return result;
956 }
957
958 /* get a list of trusted domains */
959 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
960                                 TALLOC_CTX *mem_ctx,
961                                 uint32 *num_domains,
962                                 char ***names,
963                                 char ***alt_names,
964                                 DOM_SID **dom_sids)
965 {
966         CLI_POLICY_HND *hnd;
967         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
968         uint32 enum_ctx = 0;
969         int retry;
970
971         DEBUG(3,("rpc: trusted_domains\n"));
972
973         *num_domains = 0;
974         *names = NULL;
975         *alt_names = NULL;
976         *dom_sids = NULL;
977
978         retry = 0;
979         do {
980                 if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(find_our_domain(), &hnd)))
981                         goto done;
982
983                 result = STATUS_MORE_ENTRIES;
984
985                 while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
986                         uint32 start_idx, num;
987                         char **tmp_names;
988                         DOM_SID *tmp_sids;
989                         int i;
990
991                         result = cli_lsa_enum_trust_dom(hnd->cli, mem_ctx,
992                                                         &hnd->pol, &enum_ctx,
993                                                         &num, &tmp_names,
994                                                         &tmp_sids);
995
996                         if (!NT_STATUS_IS_OK(result) &&
997                             !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
998                                 break;
999
1000                         start_idx = *num_domains;
1001                         *num_domains += num;
1002                         *names = TALLOC_REALLOC_ARRAY(mem_ctx, *names,
1003                                                       char *, *num_domains);
1004                         *dom_sids = TALLOC_REALLOC_ARRAY(mem_ctx, *dom_sids,
1005                                                          DOM_SID,
1006                                                          *num_domains);
1007                         if ((*names == NULL) || (*dom_sids == NULL))
1008                                 return NT_STATUS_NO_MEMORY;
1009
1010                         for (i=0; i<num; i++) {
1011                                 (*names)[start_idx+i] = tmp_names[i];
1012                                 (*dom_sids)[start_idx+i] = tmp_sids[i];
1013                         }
1014                 }
1015         } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) &&  hnd && hnd->cli && hnd->cli->fd == -1);
1016
1017 done:
1018         return result;
1019 }
1020
1021 /* find the domain sid for a domain */
1022 static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid)
1023 {
1024         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1025         TALLOC_CTX *mem_ctx;
1026         CLI_POLICY_HND *hnd;
1027         char *level5_dom;
1028         DOM_SID *alloc_sid;
1029         int retry;
1030
1031         DEBUG(3,("rpc: domain_sid\n"));
1032
1033         if (!(mem_ctx = talloc_init("domain_sid[rpc]")))
1034                 return NT_STATUS_NO_MEMORY;
1035
1036         retry = 0;
1037         do {
1038                 /* Get lsa handle */
1039                 if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(domain, &hnd)))
1040                         goto done;
1041
1042                 result = cli_lsa_query_info_policy(hnd->cli, mem_ctx,
1043                                            &hnd->pol, 0x05, &level5_dom, &alloc_sid);
1044         } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) &&  hnd && hnd->cli && hnd->cli->fd == -1);
1045
1046         if (NT_STATUS_IS_OK(result)) {
1047                 if (alloc_sid) {
1048                         sid_copy(sid, alloc_sid);
1049                 } else {
1050                         result = NT_STATUS_NO_MEMORY;
1051                 }
1052         }
1053
1054 done:
1055         talloc_destroy(mem_ctx);
1056         return result;
1057 }
1058
1059 /* find alternate names list for the domain - none for rpc */
1060 static NTSTATUS alternate_name(struct winbindd_domain *domain)
1061 {
1062         return NT_STATUS_OK;
1063 }
1064
1065
1066 /* the rpc backend methods are exposed via this structure */
1067 struct winbindd_methods msrpc_methods = {
1068         False,
1069         query_user_list,
1070         enum_dom_groups,
1071         enum_local_groups,
1072         msrpc_name_to_sid,
1073         msrpc_sid_to_name,
1074         query_user,
1075         lookup_usergroups,
1076         msrpc_lookup_useraliases,
1077         lookup_groupmem,
1078         sequence_number,
1079         trusted_domains,
1080         domain_sid,
1081         alternate_name
1082 };