r22589: Make TALLOC_ARRAY consistent across all uses.
[tprouty/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         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 lsa_SidType *type)
245 {
246         NTSTATUS result;
247         DOM_SID *sids = NULL;
248         enum lsa_SidType *types = NULL;
249         char *full_name = NULL;
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         ws_name_return( full_name, WB_REPLACE_CHAR );
266
267         DEBUG(3,("name_to_sid [rpc] %s for domain %s\n", full_name?full_name:"", domain_name ));
268
269         result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
270         if (!NT_STATUS_IS_OK(result))
271                 return result;
272
273         result = rpccli_lsa_lookup_names(cli, mem_ctx, &lsa_policy, 1, 
274                                          (const char**) &full_name, NULL, &sids, &types);
275         
276         if (!NT_STATUS_IS_OK(result))
277                 return result;
278
279         /* Return rid and type if lookup successful */
280
281         sid_copy(sid, &sids[0]);
282         *type = types[0];
283
284         return NT_STATUS_OK;
285 }
286
287 /*
288   convert a domain SID to a user or group name
289 */
290 NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain,
291                             TALLOC_CTX *mem_ctx,
292                             const DOM_SID *sid,
293                             char **domain_name,
294                             char **name,
295                             enum lsa_SidType *type)
296 {
297         char **domains;
298         char **names;
299         enum lsa_SidType *types;
300         NTSTATUS result;
301         struct rpc_pipe_client *cli;
302         POLICY_HND lsa_policy;
303
304         DEBUG(3,("sid_to_name [rpc] %s for domain %s\n", sid_string_static(sid),
305                         domain->name ));
306
307         result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
308         if (!NT_STATUS_IS_OK(result))
309                 return result;
310
311         result = rpccli_lsa_lookup_sids(cli, mem_ctx, &lsa_policy,
312                                         1, sid, &domains, &names, &types);
313         if (!NT_STATUS_IS_OK(result))
314                 return result;
315
316         *type = (enum lsa_SidType)types[0];
317         *domain_name = domains[0];
318         *name = names[0];
319
320         ws_name_replace( *name, WB_REPLACE_CHAR );      
321                 
322         DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name));
323         return NT_STATUS_OK;
324 }
325
326 NTSTATUS msrpc_rids_to_names(struct winbindd_domain *domain,
327                              TALLOC_CTX *mem_ctx,
328                              const DOM_SID *sid,
329                              uint32 *rids,
330                              size_t num_rids,
331                              char **domain_name,
332                              char ***names,
333                              enum lsa_SidType **types)
334 {
335         char **domains;
336         NTSTATUS result;
337         struct rpc_pipe_client *cli;
338         POLICY_HND lsa_policy;
339         DOM_SID *sids;
340         size_t i;
341         char **ret_names;
342
343         DEBUG(3, ("rids_to_names [rpc] for domain %s\n", domain->name ));
344
345         if (num_rids) {
346                 sids = TALLOC_ARRAY(mem_ctx, DOM_SID, num_rids);
347                 if (sids == NULL) {
348                         return NT_STATUS_NO_MEMORY;
349                 }
350         } else {
351                 sids = NULL;
352         }
353
354         for (i=0; i<num_rids; i++) {
355                 if (!sid_compose(&sids[i], sid, rids[i])) {
356                         return NT_STATUS_INTERNAL_ERROR;
357                 }
358         }
359
360         result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
361         if (!NT_STATUS_IS_OK(result)) {
362                 return result;
363         }
364
365         result = rpccli_lsa_lookup_sids(cli, mem_ctx, &lsa_policy,
366                                         num_rids, sids, &domains,
367                                         names, types);
368         if (!NT_STATUS_IS_OK(result) &&
369             !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
370                 return result;
371         }
372
373         ret_names = *names;
374         for (i=0; i<num_rids; i++) {
375                 if ((*types)[i] != SID_NAME_UNKNOWN) {
376                         ws_name_replace( ret_names[i], WB_REPLACE_CHAR );
377                         *domain_name = domains[i];
378                 }
379         }
380
381         return result;
382 }
383
384 /* Lookup user information from a rid or username. */
385 static NTSTATUS query_user(struct winbindd_domain *domain, 
386                            TALLOC_CTX *mem_ctx, 
387                            const DOM_SID *user_sid, 
388                            WINBIND_USERINFO *user_info)
389 {
390         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
391         POLICY_HND dom_pol, user_pol;
392         SAM_USERINFO_CTR *ctr;
393         fstring sid_string;
394         uint32 user_rid;
395         NET_USER_INFO_3 *user;
396         struct rpc_pipe_client *cli;
397
398         DEBUG(3,("rpc: query_user sid=%s\n",
399                  sid_to_string(sid_string, user_sid)));
400
401         if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
402                 return NT_STATUS_UNSUCCESSFUL;
403         
404         /* try netsamlogon cache first */
405                         
406         if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL ) 
407         {
408                                 
409                 DEBUG(5,("query_user: Cache lookup succeeded for %s\n", 
410                         sid_string_static(user_sid)));
411
412                 sid_compose(&user_info->user_sid, &domain->sid, user_rid);
413                 sid_compose(&user_info->group_sid, &domain->sid,
414                             user->group_rid);
415                                 
416                 user_info->acct_name = unistr2_tdup(mem_ctx,
417                                                     &user->uni_user_name);
418                 user_info->full_name = unistr2_tdup(mem_ctx,
419                                                     &user->uni_full_name);
420                 
421                 user_info->homedir = NULL;
422                 user_info->shell = NULL;
423                 user_info->primary_gid = (gid_t)-1;
424                                                 
425                 SAFE_FREE(user);
426                                 
427                 return NT_STATUS_OK;
428         }
429         
430         /* no cache; hit the wire */
431                 
432         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
433         if (!NT_STATUS_IS_OK(result))
434                 return result;
435
436         /* Get user handle */
437         result = rpccli_samr_open_user(cli, mem_ctx, &dom_pol,
438                                        SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid,
439                                        &user_pol);
440
441         if (!NT_STATUS_IS_OK(result))
442                 return result;
443
444         /* Get user info */
445         result = rpccli_samr_query_userinfo(cli, mem_ctx, &user_pol,
446                                             0x15, &ctr);
447
448         rpccli_samr_close(cli, mem_ctx, &user_pol);
449
450         if (!NT_STATUS_IS_OK(result))
451                 return result;
452
453         sid_compose(&user_info->user_sid, &domain->sid, user_rid);
454         sid_compose(&user_info->group_sid, &domain->sid,
455                     ctr->info.id21->group_rid);
456         user_info->acct_name = unistr2_tdup(mem_ctx, 
457                                             &ctr->info.id21->uni_user_name);
458         user_info->full_name = unistr2_tdup(mem_ctx, 
459                                             &ctr->info.id21->uni_full_name);
460         user_info->homedir = NULL;
461         user_info->shell = NULL;
462         user_info->primary_gid = (gid_t)-1;
463
464         return NT_STATUS_OK;
465 }                                   
466
467 /* Lookup groups a user is a member of.  I wish Unix had a call like this! */
468 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
469                                   TALLOC_CTX *mem_ctx,
470                                   const DOM_SID *user_sid,
471                                   uint32 *num_groups, DOM_SID **user_grpsids)
472 {
473         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
474         POLICY_HND dom_pol, user_pol;
475         uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
476         DOM_GID *user_groups;
477         unsigned int i;
478         fstring sid_string;
479         uint32 user_rid;
480         struct rpc_pipe_client *cli;
481
482         DEBUG(3,("rpc: lookup_usergroups sid=%s\n",
483                  sid_to_string(sid_string, user_sid)));
484
485         if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
486                 return NT_STATUS_UNSUCCESSFUL;
487
488         *num_groups = 0;
489         *user_grpsids = NULL;
490
491         /* so lets see if we have a cached user_info_3 */
492         result = lookup_usergroups_cached(domain, mem_ctx, user_sid, 
493                                           num_groups, user_grpsids);
494
495         if (NT_STATUS_IS_OK(result)) {
496                 return NT_STATUS_OK;
497         }
498
499         /* no cache; hit the wire */
500         
501         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
502         if (!NT_STATUS_IS_OK(result))
503                 return result;
504
505         /* Get user handle */
506         result = rpccli_samr_open_user(cli, mem_ctx, &dom_pol,
507                                         des_access, user_rid, &user_pol);
508
509         if (!NT_STATUS_IS_OK(result))
510                 return result;
511
512         /* Query user rids */
513         result = rpccli_samr_query_usergroups(cli, mem_ctx, &user_pol, 
514                                            num_groups, &user_groups);
515
516         rpccli_samr_close(cli, mem_ctx, &user_pol);
517
518         if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0)
519                 return result;
520
521         (*user_grpsids) = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_groups);
522         if (!(*user_grpsids))
523                 return NT_STATUS_NO_MEMORY;
524
525         for (i=0;i<(*num_groups);i++) {
526                 sid_copy(&((*user_grpsids)[i]), &domain->sid);
527                 sid_append_rid(&((*user_grpsids)[i]),
528                                 user_groups[i].g_rid);
529         }
530         
531         return NT_STATUS_OK;
532 }
533
534 NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain,
535                                   TALLOC_CTX *mem_ctx,
536                                   uint32 num_sids, const DOM_SID *sids,
537                                   uint32 *num_aliases, uint32 **alias_rids)
538 {
539         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
540         POLICY_HND dom_pol;
541         DOM_SID2 *query_sids;
542         uint32 num_query_sids = 0;
543         int i;
544         struct rpc_pipe_client *cli;
545         uint32 *alias_rids_query, num_aliases_query;
546         int rangesize = MAX_SAM_ENTRIES_W2K;
547         uint32 total_sids = 0;
548         int num_queries = 1;
549
550         *num_aliases = 0;
551         *alias_rids = NULL;
552
553         DEBUG(3,("rpc: lookup_useraliases\n"));
554
555         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
556         if (!NT_STATUS_IS_OK(result))
557                 return result;
558
559         do {
560                 /* prepare query */
561
562                 num_query_sids = MIN(num_sids - total_sids, rangesize);
563
564                 DEBUG(10,("rpc: lookup_useraliases: entering query %d for %d sids\n", 
565                         num_queries, num_query_sids));  
566
567                 if (num_query_sids) {
568                         query_sids = TALLOC_ARRAY(mem_ctx, DOM_SID2, num_query_sids);
569                         if (query_sids == NULL) {
570                                 return NT_STATUS_NO_MEMORY;
571                         }
572                 } else {
573                         query_sids = NULL;
574                 }
575
576                 for (i=0; i<num_query_sids; i++) {
577                         sid_copy(&query_sids[i].sid, &sids[total_sids++]);
578                         query_sids[i].num_auths = query_sids[i].sid.num_auths;
579                 }
580
581                 /* do request */
582
583                 result = rpccli_samr_query_useraliases(cli, mem_ctx, &dom_pol,
584                                                        num_query_sids, query_sids,
585                                                        &num_aliases_query, 
586                                                        &alias_rids_query);
587
588                 if (!NT_STATUS_IS_OK(result)) {
589                         *num_aliases = 0;
590                         *alias_rids = NULL;
591                         TALLOC_FREE(query_sids);
592                         goto done;
593                 }
594
595                 /* process output */
596
597                 for (i=0; i<num_aliases_query; i++) {
598                         size_t na = *num_aliases;
599                         if (!add_rid_to_array_unique(mem_ctx, alias_rids_query[i], 
600                                                 alias_rids, &na)) {
601                                 return NT_STATUS_NO_MEMORY;
602                         }
603                         *num_aliases = na;
604                 }
605
606                 TALLOC_FREE(query_sids);
607
608                 num_queries++;
609
610         } while (total_sids < num_sids);
611
612  done:
613         DEBUG(10,("rpc: lookup_useraliases: got %d aliases in %d queries "
614                 "(rangesize: %d)\n", *num_aliases, num_queries, rangesize));
615
616         return result;
617 }
618
619
620 /* Lookup group membership given a rid.   */
621 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
622                                 TALLOC_CTX *mem_ctx,
623                                 const DOM_SID *group_sid, uint32 *num_names, 
624                                 DOM_SID **sid_mem, char ***names, 
625                                 uint32 **name_types)
626 {
627         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
628         uint32 i, total_names = 0;
629         POLICY_HND dom_pol, group_pol;
630         uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
631         uint32 *rid_mem = NULL;
632         uint32 group_rid;
633         unsigned int j;
634         fstring sid_string;
635         struct rpc_pipe_client *cli;
636         unsigned int orig_timeout;
637
638         DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain->name,
639                   sid_to_string(sid_string, group_sid)));
640
641         if (!sid_peek_check_rid(&domain->sid, group_sid, &group_rid))
642                 return NT_STATUS_UNSUCCESSFUL;
643
644         *num_names = 0;
645
646         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
647         if (!NT_STATUS_IS_OK(result))
648                 return result;
649
650         result = rpccli_samr_open_group(cli, mem_ctx, &dom_pol,
651                                         des_access, group_rid, &group_pol);
652
653         if (!NT_STATUS_IS_OK(result))
654                 return result;
655
656         /* Step #1: Get a list of user rids that are the members of the
657            group. */
658
659         /* This call can take a long time - allow the server to time out.
660            35 seconds should do it. */
661
662         orig_timeout = cli_set_timeout(cli->cli, 35000);
663
664         result = rpccli_samr_query_groupmem(cli, mem_ctx,
665                                             &group_pol, num_names, &rid_mem,
666                                             name_types);
667
668         /* And restore our original timeout. */
669         cli_set_timeout(cli->cli, orig_timeout);
670
671         rpccli_samr_close(cli, mem_ctx, &group_pol);
672
673         if (!NT_STATUS_IS_OK(result))
674                 return result;
675
676         if (!*num_names) {
677                 names = NULL;
678                 name_types = NULL;
679                 sid_mem = NULL;
680                 return NT_STATUS_OK;
681         }
682
683         /* Step #2: Convert list of rids into list of usernames.  Do this
684            in bunches of ~1000 to avoid crashing NT4.  It looks like there
685            is a buffer overflow or something like that lurking around
686            somewhere. */
687
688 #define MAX_LOOKUP_RIDS 900
689
690         *names = TALLOC_ZERO_ARRAY(mem_ctx, char *, *num_names);
691         *name_types = TALLOC_ZERO_ARRAY(mem_ctx, uint32, *num_names);
692         *sid_mem = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, *num_names);
693
694         for (j=0;j<(*num_names);j++)
695                 sid_compose(&(*sid_mem)[j], &domain->sid, rid_mem[j]);
696         
697         if (*num_names>0 && (!*names || !*name_types))
698                 return NT_STATUS_NO_MEMORY;
699
700         for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) {
701                 int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS);
702                 uint32 tmp_num_names = 0;
703                 char **tmp_names = NULL;
704                 uint32 *tmp_types = NULL;
705
706                 /* Lookup a chunk of rids */
707
708                 result = rpccli_samr_lookup_rids(cli, mem_ctx,
709                                                  &dom_pol,
710                                                  num_lookup_rids,
711                                                  &rid_mem[i],
712                                                  &tmp_num_names,
713                                                  &tmp_names, &tmp_types);
714
715                 /* see if we have a real error (and yes the
716                    STATUS_SOME_UNMAPPED is the one returned from 2k) */
717                 
718                 if (!NT_STATUS_IS_OK(result) &&
719                     !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
720                         return result;
721                         
722                 /* Copy result into array.  The talloc system will take
723                    care of freeing the temporary arrays later on. */
724
725                 memcpy(&(*names)[i], tmp_names, sizeof(char *) * 
726                        tmp_num_names);
727
728                 memcpy(&(*name_types)[i], tmp_types, sizeof(uint32) *
729                        tmp_num_names);
730                 
731                 total_names += tmp_num_names;
732         }
733
734         *num_names = total_names;
735
736         return NT_STATUS_OK;
737 }
738
739 #ifdef HAVE_LDAP
740
741 #include <ldap.h>
742
743 static int get_ldap_seq(const char *server, int port, uint32 *seq)
744 {
745         int ret = -1;
746         struct timeval to;
747         const char *attrs[] = {"highestCommittedUSN", NULL};
748         LDAPMessage *res = NULL;
749         char **values = NULL;
750         LDAP *ldp = NULL;
751
752         *seq = DOM_SEQUENCE_NONE;
753
754         /*
755          * Parameterised (5) second timeout on open. This is needed as the
756          * search timeout doesn't seem to apply to doing an open as well. JRA.
757          */
758
759         ldp = ldap_open_with_timeout(server, port, lp_ldap_timeout());
760         if (ldp == NULL)
761                 return -1;
762
763         /* Timeout if no response within 20 seconds. */
764         to.tv_sec = 10;
765         to.tv_usec = 0;
766
767         if (ldap_search_st(ldp, "", LDAP_SCOPE_BASE, "(objectclass=*)",
768                            CONST_DISCARD(char **, attrs), 0, &to, &res))
769                 goto done;
770
771         if (ldap_count_entries(ldp, res) != 1)
772                 goto done;
773
774         values = ldap_get_values(ldp, res, "highestCommittedUSN");
775         if (!values || !values[0])
776                 goto done;
777
778         *seq = atoi(values[0]);
779         ret = 0;
780
781   done:
782
783         if (values)
784                 ldap_value_free(values);
785         if (res)
786                 ldap_msgfree(res);
787         if (ldp)
788                 ldap_unbind(ldp);
789         return ret;
790 }
791
792 /**********************************************************************
793  Get the sequence number for a Windows AD native mode domain using
794  LDAP queries. 
795 **********************************************************************/
796
797 static int get_ldap_sequence_number(struct winbindd_domain *domain, uint32 *seq)
798 {
799         int ret = -1;
800         fstring ipstr;
801
802         fstrcpy( ipstr, inet_ntoa(domain->dcaddr.sin_addr));
803         if ((ret = get_ldap_seq( ipstr, LDAP_PORT, seq)) == 0) {
804                 DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence "
805                           "number for Domain (%s) from DC (%s)\n", 
806                         domain->name, ipstr));
807         } 
808         return ret;
809 }
810
811 #endif /* HAVE_LDAP */
812
813 /* find the sequence number for a domain */
814 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
815 {
816         TALLOC_CTX *mem_ctx;
817         SAM_UNK_CTR ctr;
818         NTSTATUS result;
819         POLICY_HND dom_pol;
820         BOOL got_seq_num = False;
821         struct rpc_pipe_client *cli;
822
823         DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name));
824
825         *seq = DOM_SEQUENCE_NONE;
826
827         if (!(mem_ctx = talloc_init("sequence_number[rpc]")))
828                 return NT_STATUS_NO_MEMORY;
829
830 #ifdef HAVE_LDAP
831         if ( domain->native_mode ) 
832         {
833                 int res;
834
835                 DEBUG(8,("using get_ldap_seq() to retrieve the "
836                          "sequence number\n"));
837
838                 res =  get_ldap_sequence_number( domain, seq );
839                 if (res == 0)
840                 {                       
841                         result = NT_STATUS_OK;
842                         DEBUG(10,("domain_sequence_number: LDAP for "
843                                   "domain %s is %u\n",
844                                   domain->name, *seq));
845                         goto done;
846                 }
847
848                 DEBUG(10,("domain_sequence_number: failed to get LDAP "
849                           "sequence number for domain %s\n",
850                           domain->name ));
851         }
852 #endif /* HAVE_LDAP */
853
854         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
855         if (!NT_STATUS_IS_OK(result)) {
856                 goto done;
857         }
858
859         /* Query domain info */
860
861         result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 8, &ctr);
862
863         if (NT_STATUS_IS_OK(result)) {
864                 *seq = ctr.info.inf8.seq_num;
865                 got_seq_num = True;
866                 goto seq_num;
867         }
868
869         /* retry with info-level 2 in case the dc does not support info-level 8
870          * (like all older samba2 and samba3 dc's - Guenther */
871
872         result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 2, &ctr);
873         
874         if (NT_STATUS_IS_OK(result)) {
875                 *seq = ctr.info.inf2.seq_num;
876                 got_seq_num = True;
877         }
878
879  seq_num:
880         if (got_seq_num) {
881                 DEBUG(10,("domain_sequence_number: for domain %s is %u\n",
882                           domain->name, (unsigned)*seq));
883         } else {
884                 DEBUG(10,("domain_sequence_number: failed to get sequence "
885                           "number (%u) for domain %s\n",
886                           (unsigned)*seq, domain->name ));
887         }
888
889   done:
890
891         talloc_destroy(mem_ctx);
892
893         return result;
894 }
895
896 /* get a list of trusted domains */
897 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
898                                 TALLOC_CTX *mem_ctx,
899                                 uint32 *num_domains,
900                                 char ***names,
901                                 char ***alt_names,
902                                 DOM_SID **dom_sids)
903 {
904         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
905         uint32 enum_ctx = 0;
906         struct rpc_pipe_client *cli;
907         POLICY_HND lsa_policy;
908
909         DEBUG(3,("rpc: trusted_domains\n"));
910
911         *num_domains = 0;
912         *names = NULL;
913         *alt_names = NULL;
914         *dom_sids = NULL;
915
916         result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
917         if (!NT_STATUS_IS_OK(result))
918                 return result;
919
920         result = STATUS_MORE_ENTRIES;
921
922         while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
923                 uint32 start_idx, num;
924                 char **tmp_names;
925                 DOM_SID *tmp_sids;
926                 int i;
927
928                 result = rpccli_lsa_enum_trust_dom(cli, mem_ctx,
929                                                    &lsa_policy, &enum_ctx,
930                                                    &num, &tmp_names,
931                                                    &tmp_sids);
932
933                 if (!NT_STATUS_IS_OK(result) &&
934                     !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
935                         break;
936
937                 start_idx = *num_domains;
938                 *num_domains += num;
939                 *names = TALLOC_REALLOC_ARRAY(mem_ctx, *names,
940                                               char *, *num_domains);
941                 *dom_sids = TALLOC_REALLOC_ARRAY(mem_ctx, *dom_sids,
942                                                  DOM_SID, *num_domains);
943                 *alt_names = TALLOC_REALLOC_ARRAY(mem_ctx, *alt_names,
944                                                  char *, *num_domains);
945                 if ((*names == NULL) || (*dom_sids == NULL) ||
946                     (*alt_names == NULL))
947                         return NT_STATUS_NO_MEMORY;
948
949                 for (i=0; i<num; i++) {
950                         (*names)[start_idx+i] = tmp_names[i];
951                         (*dom_sids)[start_idx+i] = tmp_sids[i];
952                         (*alt_names)[start_idx+i] = talloc_strdup(mem_ctx, "");
953                 }
954         }
955         return result;
956 }
957
958 /* find the lockout policy for a domain */
959 NTSTATUS msrpc_lockout_policy(struct winbindd_domain *domain, 
960                               TALLOC_CTX *mem_ctx,
961                               SAM_UNK_INFO_12 *lockout_policy)
962 {
963         NTSTATUS result;
964         struct rpc_pipe_client *cli;
965         POLICY_HND dom_pol;
966         SAM_UNK_CTR ctr;
967
968         DEBUG(10,("rpc: fetch lockout policy for %s\n", domain->name));
969
970         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
971         if (!NT_STATUS_IS_OK(result)) {
972                 goto done;
973         }
974
975         result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 12, &ctr);
976         if (!NT_STATUS_IS_OK(result)) {
977                 goto done;
978         }
979
980         *lockout_policy = ctr.info.inf12;
981
982         DEBUG(10,("msrpc_lockout_policy: bad_attempt_lockout %d\n", 
983                 ctr.info.inf12.bad_attempt_lockout));
984
985   done:
986
987         return result;
988 }
989
990 /* find the password policy for a domain */
991 NTSTATUS msrpc_password_policy(struct winbindd_domain *domain, 
992                                TALLOC_CTX *mem_ctx,
993                                SAM_UNK_INFO_1 *password_policy)
994 {
995         NTSTATUS result;
996         struct rpc_pipe_client *cli;
997         POLICY_HND dom_pol;
998         SAM_UNK_CTR ctr;
999
1000         DEBUG(10,("rpc: fetch password policy for %s\n", domain->name));
1001
1002         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
1003         if (!NT_STATUS_IS_OK(result)) {
1004                 goto done;
1005         }
1006
1007         result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 1, &ctr);
1008         if (!NT_STATUS_IS_OK(result)) {
1009                 goto done;
1010         }
1011
1012         *password_policy = ctr.info.inf1;
1013
1014         DEBUG(10,("msrpc_password_policy: min_length_password %d\n", 
1015                 ctr.info.inf1.min_length_password));
1016
1017   done:
1018
1019         return result;
1020 }
1021
1022
1023 /* the rpc backend methods are exposed via this structure */
1024 struct winbindd_methods msrpc_methods = {
1025         False,
1026         query_user_list,
1027         enum_dom_groups,
1028         enum_local_groups,
1029         msrpc_name_to_sid,
1030         msrpc_sid_to_name,
1031         msrpc_rids_to_names,
1032         query_user,
1033         lookup_usergroups,
1034         msrpc_lookup_useraliases,
1035         lookup_groupmem,
1036         sequence_number,
1037         msrpc_lockout_policy,
1038         msrpc_password_policy,
1039         trusted_domains,
1040 };