r5428: Apply some const. LDAP attribs should now be declared const char *attr[]....
[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    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, 1000, /* flags */
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=*)", &attrs[0], 0, &to, &res))
792                 goto done;
793
794         if (ldap_count_entries(ldp, res) != 1)
795                 goto done;
796
797         values = ldap_get_values(ldp, res, "highestCommittedUSN");
798         if (!values || !values[0])
799                 goto done;
800
801         *seq = atoi(values[0]);
802         ret = 0;
803
804   done:
805
806         if (values)
807                 ldap_value_free(values);
808         if (res)
809                 ldap_msgfree(res);
810         if (ldp)
811                 ldap_unbind(ldp);
812         return ret;
813 }
814
815 /**********************************************************************
816  Get the sequence number for a Windows AD native mode domain using
817  LDAP queries
818 **********************************************************************/
819
820 static int get_ldap_sequence_number( const char* domain, uint32 *seq)
821 {
822         int ret = -1;
823         int i, port = LDAP_PORT;
824         struct ip_service *ip_list = NULL;
825         int count;
826         
827         if ( !get_sorted_dc_list(domain, &ip_list, &count, False) ) {
828                 DEBUG(3, ("Could not look up dc's for domain %s\n", domain));
829                 return False;
830         }
831
832         /* Finally return first DC that we can contact */
833
834         for (i = 0; i < count; i++) {
835                 fstring ipstr;
836
837                 /* since the is an LDAP lookup, default to the LDAP_PORT is not set */
838                 port = (ip_list[i].port!= PORT_NONE) ? ip_list[i].port : LDAP_PORT;
839
840                 fstrcpy( ipstr, inet_ntoa(ip_list[i].ip) );
841                 
842                 if (is_zero_ip(ip_list[i].ip))
843                         continue;
844
845                 if ( (ret = get_ldap_seq( ipstr, port,  seq)) == 0 )
846                         goto done;
847
848                 /* add to failed connection cache */
849                 add_failed_connection_entry( domain, ipstr, NT_STATUS_UNSUCCESSFUL );
850         }
851
852 done:
853         if ( ret == 0 ) {
854                 DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence number for Domain (%s) from DC (%s:%d)\n", 
855                         domain, inet_ntoa(ip_list[i].ip), port));
856         }
857
858         SAFE_FREE(ip_list);
859
860         return ret;
861 }
862
863 #endif /* HAVE_LDAP */
864
865 /* find the sequence number for a domain */
866 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
867 {
868         TALLOC_CTX *mem_ctx;
869         CLI_POLICY_HND *hnd;
870         SAM_UNK_CTR ctr;
871         NTSTATUS result;
872         POLICY_HND dom_pol;
873         BOOL got_dom_pol = False;
874         BOOL got_seq_num = False;
875         uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
876         int retry;
877
878         DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name));
879
880         *seq = DOM_SEQUENCE_NONE;
881
882         if (!(mem_ctx = talloc_init("sequence_number[rpc]")))
883                 return NT_STATUS_NO_MEMORY;
884
885         retry = 0;
886         do {
887 #ifdef HAVE_LDAP
888                 if ( domain->native_mode ) 
889                 {
890                         DEBUG(8,("using get_ldap_seq() to retrieve the sequence number\n"));
891
892                         if ( get_ldap_sequence_number( domain->name, seq ) == 0 ) {                     
893                                 result = NT_STATUS_OK;
894                                 DEBUG(10,("domain_sequence_number: LDAP for domain %s is %u\n",
895                                         domain->name, *seq));
896                                 goto done;
897                         }
898
899                         DEBUG(10,("domain_sequence_number: failed to get LDAP sequence number for domain %s\n",
900                         domain->name ));
901                 }
902 #endif /* HAVE_LDAP */
903                 /* Get sam handle */
904                 if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)))
905                         goto done;
906
907                 /* Get domain handle */
908                 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol, 
909                                       des_access, &domain->sid, &dom_pol);
910         } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
911
912         if (!NT_STATUS_IS_OK(result))
913                 goto done;
914
915         got_dom_pol = True;
916
917         /* Query domain info */
918
919         result = cli_samr_query_dom_info(hnd->cli, mem_ctx, &dom_pol,
920                                          8, &ctr);
921
922         if (NT_STATUS_IS_OK(result)) {
923                 *seq = ctr.info.inf8.seq_num.low;
924                 got_seq_num = True;
925                 goto seq_num;
926         }
927
928         /* retry with info-level 2 in case the dc does not support info-level 8
929          * (like all older samba2 and samba3 dc's - Guenther */
930
931         result = cli_samr_query_dom_info(hnd->cli, mem_ctx, &dom_pol,
932                                          2, &ctr);
933         
934         if (NT_STATUS_IS_OK(result)) {
935                 *seq = ctr.info.inf2.seq_num.low;
936                 got_seq_num = True;
937         }
938
939  seq_num:
940         if (got_seq_num) {
941                 DEBUG(10,("domain_sequence_number: for domain %s is %u\n", domain->name, (unsigned)*seq));
942         } else {
943                 DEBUG(10,("domain_sequence_number: failed to get sequence number (%u) for domain %s\n",
944                         (unsigned)*seq, domain->name ));
945         }
946
947   done:
948
949         if (got_dom_pol)
950                 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
951
952         talloc_destroy(mem_ctx);
953
954         return result;
955 }
956
957 /* get a list of trusted domains */
958 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
959                                 TALLOC_CTX *mem_ctx,
960                                 uint32 *num_domains,
961                                 char ***names,
962                                 char ***alt_names,
963                                 DOM_SID **dom_sids)
964 {
965         CLI_POLICY_HND *hnd;
966         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
967         uint32 enum_ctx = 0;
968         int retry;
969
970         DEBUG(3,("rpc: trusted_domains\n"));
971
972         *num_domains = 0;
973         *alt_names = NULL;
974
975         retry = 0;
976         do {
977                 if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(find_our_domain(), &hnd)))
978                         goto done;
979
980                 result = cli_lsa_enum_trust_dom(hnd->cli, mem_ctx,
981                                                 &hnd->pol, &enum_ctx,
982                                                 num_domains, names, dom_sids);
983         } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) &&  hnd && hnd->cli && hnd->cli->fd == -1);
984
985 done:
986         return result;
987 }
988
989 /* find the domain sid for a domain */
990 static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid)
991 {
992         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
993         TALLOC_CTX *mem_ctx;
994         CLI_POLICY_HND *hnd;
995         char *level5_dom;
996         DOM_SID *alloc_sid;
997         int retry;
998
999         DEBUG(3,("rpc: domain_sid\n"));
1000
1001         if (!(mem_ctx = talloc_init("domain_sid[rpc]")))
1002                 return NT_STATUS_NO_MEMORY;
1003
1004         retry = 0;
1005         do {
1006                 /* Get lsa handle */
1007                 if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(domain, &hnd)))
1008                         goto done;
1009
1010                 result = cli_lsa_query_info_policy(hnd->cli, mem_ctx,
1011                                            &hnd->pol, 0x05, &level5_dom, &alloc_sid);
1012         } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) &&  hnd && hnd->cli && hnd->cli->fd == -1);
1013
1014         if (NT_STATUS_IS_OK(result)) {
1015                 if (alloc_sid) {
1016                         sid_copy(sid, alloc_sid);
1017                 } else {
1018                         result = NT_STATUS_NO_MEMORY;
1019                 }
1020         }
1021
1022 done:
1023         talloc_destroy(mem_ctx);
1024         return result;
1025 }
1026
1027 /* find alternate names list for the domain - none for rpc */
1028 static NTSTATUS alternate_name(struct winbindd_domain *domain)
1029 {
1030         return NT_STATUS_OK;
1031 }
1032
1033
1034 /* the rpc backend methods are exposed via this structure */
1035 struct winbindd_methods msrpc_methods = {
1036         False,
1037         query_user_list,
1038         enum_dom_groups,
1039         enum_local_groups,
1040         msrpc_name_to_sid,
1041         msrpc_sid_to_name,
1042         query_user,
1043         lookup_usergroups,
1044         msrpc_lookup_useraliases,
1045         lookup_groupmem,
1046         sequence_number,
1047         trusted_domains,
1048         domain_sid,
1049         alternate_name
1050 };