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