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