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