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