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