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