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