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