82e782b9db09b131026eb399babd98fb237731c7
[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         if ( !winbindd_can_contact_domain( domain ) ) {
497                 DEBUG(10,("query_user: No incoming trust for domain %s\n",
498                           domain->name));
499                 return NT_STATUS_OK;
500         }
501
502         if ( !winbindd_can_contact_domain( domain ) ) {
503                 DEBUG(10,("query_user: No incoming trust for domain %s\n",
504                           domain->name));
505                 return NT_STATUS_OK;
506         }
507
508         /* no cache; hit the wire */
509
510         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
511         if (!NT_STATUS_IS_OK(result))
512                 return result;
513
514         /* Get user handle */
515         result = rpccli_samr_OpenUser(cli, mem_ctx,
516                                       &dom_pol,
517                                       SEC_FLAG_MAXIMUM_ALLOWED,
518                                       user_rid,
519                                       &user_pol);
520
521         if (!NT_STATUS_IS_OK(result))
522                 return result;
523
524         /* Get user info */
525         result = rpccli_samr_QueryUserInfo(cli, mem_ctx,
526                                            &user_pol,
527                                            0x15,
528                                            &info);
529
530         rpccli_samr_Close(cli, mem_ctx, &user_pol);
531
532         if (!NT_STATUS_IS_OK(result))
533                 return result;
534
535         sid_compose(&user_info->user_sid, &domain->sid, user_rid);
536         sid_compose(&user_info->group_sid, &domain->sid,
537                     info->info21.primary_gid);
538         user_info->acct_name = talloc_strdup(mem_ctx,
539                                              info->info21.account_name.string);
540         user_info->full_name = talloc_strdup(mem_ctx,
541                                              info->info21.full_name.string);
542         user_info->homedir = NULL;
543         user_info->shell = NULL;
544         user_info->primary_gid = (gid_t)-1;
545
546         return NT_STATUS_OK;
547 }                                   
548
549 /* Lookup groups a user is a member of.  I wish Unix had a call like this! */
550 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
551                                   TALLOC_CTX *mem_ctx,
552                                   const DOM_SID *user_sid,
553                                   uint32 *num_groups, DOM_SID **user_grpsids)
554 {
555         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
556         struct policy_handle dom_pol, user_pol;
557         uint32 des_access = SEC_FLAG_MAXIMUM_ALLOWED;
558         struct samr_RidWithAttributeArray *rid_array = NULL;
559         unsigned int i;
560         uint32 user_rid;
561         struct rpc_pipe_client *cli;
562
563         DEBUG(3,("rpc: lookup_usergroups sid=%s\n", sid_string_dbg(user_sid)));
564
565         if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
566                 return NT_STATUS_UNSUCCESSFUL;
567
568         *num_groups = 0;
569         *user_grpsids = NULL;
570
571         /* so lets see if we have a cached user_info_3 */
572         result = lookup_usergroups_cached(domain, mem_ctx, user_sid, 
573                                           num_groups, user_grpsids);
574
575         if (NT_STATUS_IS_OK(result)) {
576                 return NT_STATUS_OK;
577         }
578
579         if ( !winbindd_can_contact_domain( domain ) ) {
580                 DEBUG(10,("lookup_usergroups: No incoming trust for domain %s\n",
581                           domain->name));
582
583                 /* Tell the cache manager not to remember this one */
584
585                 return NT_STATUS_SYNCHRONIZATION_REQUIRED;
586         }
587
588         /* no cache; hit the wire */
589
590         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
591         if (!NT_STATUS_IS_OK(result))
592                 return result;
593
594         /* Get user handle */
595         result = rpccli_samr_OpenUser(cli, mem_ctx,
596                                       &dom_pol,
597                                       des_access,
598                                       user_rid,
599                                       &user_pol);
600
601         if (!NT_STATUS_IS_OK(result))
602                 return result;
603
604         /* Query user rids */
605         result = rpccli_samr_GetGroupsForUser(cli, mem_ctx,
606                                               &user_pol,
607                                               &rid_array);
608         *num_groups = rid_array->count;
609
610         rpccli_samr_Close(cli, mem_ctx, &user_pol);
611
612         if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0)
613                 return result;
614
615         (*user_grpsids) = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_groups);
616         if (!(*user_grpsids))
617                 return NT_STATUS_NO_MEMORY;
618
619         for (i=0;i<(*num_groups);i++) {
620                 sid_copy(&((*user_grpsids)[i]), &domain->sid);
621                 sid_append_rid(&((*user_grpsids)[i]),
622                                 rid_array->rids[i].rid);
623         }
624
625         return NT_STATUS_OK;
626 }
627
628 #define MAX_SAM_ENTRIES_W2K 0x400 /* 1024 */
629
630 static NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain,
631                                          TALLOC_CTX *mem_ctx,
632                                          uint32 num_sids, const DOM_SID *sids,
633                                          uint32 *num_aliases,
634                                          uint32 **alias_rids)
635 {
636         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
637         struct policy_handle dom_pol;
638         uint32 num_query_sids = 0;
639         int i;
640         struct rpc_pipe_client *cli;
641         struct samr_Ids alias_rids_query;
642         int rangesize = MAX_SAM_ENTRIES_W2K;
643         uint32 total_sids = 0;
644         int num_queries = 1;
645
646         *num_aliases = 0;
647         *alias_rids = NULL;
648
649         DEBUG(3,("rpc: lookup_useraliases\n"));
650
651         if ( !winbindd_can_contact_domain( domain ) ) {
652                 DEBUG(10,("msrpc_lookup_useraliases: No incoming trust for domain %s\n",
653                           domain->name));
654                 return NT_STATUS_OK;
655         }
656
657         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
658         if (!NT_STATUS_IS_OK(result))
659                 return result;
660
661         do {
662                 /* prepare query */
663                 struct lsa_SidArray sid_array;
664
665                 ZERO_STRUCT(sid_array);
666
667                 num_query_sids = MIN(num_sids - total_sids, rangesize);
668
669                 DEBUG(10,("rpc: lookup_useraliases: entering query %d for %d sids\n", 
670                         num_queries, num_query_sids));  
671
672                 if (num_query_sids) {
673                         sid_array.sids = TALLOC_ZERO_ARRAY(mem_ctx, struct lsa_SidPtr, num_query_sids);
674                         if (sid_array.sids == NULL) {
675                                 return NT_STATUS_NO_MEMORY;
676                         }
677                 } else {
678                         sid_array.sids = NULL;
679                 }
680
681                 for (i=0; i<num_query_sids; i++) {
682                         sid_array.sids[i].sid = sid_dup_talloc(mem_ctx, &sids[total_sids++]);
683                         if (!sid_array.sids[i].sid) {
684                                 TALLOC_FREE(sid_array.sids);
685                                 return NT_STATUS_NO_MEMORY;
686                         }
687                 }
688                 sid_array.num_sids = num_query_sids;
689
690                 /* do request */
691                 result = rpccli_samr_GetAliasMembership(cli, mem_ctx,
692                                                         &dom_pol,
693                                                         &sid_array,
694                                                         &alias_rids_query);
695
696                 if (!NT_STATUS_IS_OK(result)) {
697                         *num_aliases = 0;
698                         *alias_rids = NULL;
699                         TALLOC_FREE(sid_array.sids);
700                         goto done;
701                 }
702
703                 /* process output */
704
705                 for (i=0; i<alias_rids_query.count; i++) {
706                         size_t na = *num_aliases;
707                         if (!add_rid_to_array_unique(mem_ctx, alias_rids_query.ids[i],
708                                                 alias_rids, &na)) {
709                                 return NT_STATUS_NO_MEMORY;
710                         }
711                         *num_aliases = na;
712                 }
713
714                 TALLOC_FREE(sid_array.sids);
715
716                 num_queries++;
717
718         } while (total_sids < num_sids);
719
720  done:
721         DEBUG(10,("rpc: lookup_useraliases: got %d aliases in %d queries "
722                 "(rangesize: %d)\n", *num_aliases, num_queries, rangesize));
723
724         return result;
725 }
726
727
728 /* Lookup group membership given a rid.   */
729 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
730                                 TALLOC_CTX *mem_ctx,
731                                 const DOM_SID *group_sid,
732                                 enum lsa_SidType type,
733                                 uint32 *num_names,
734                                 DOM_SID **sid_mem, char ***names, 
735                                 uint32 **name_types)
736 {
737         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
738         uint32 i, total_names = 0;
739         struct policy_handle dom_pol, group_pol;
740         uint32 des_access = SEC_FLAG_MAXIMUM_ALLOWED;
741         uint32 *rid_mem = NULL;
742         uint32 group_rid;
743         unsigned int j, r;
744         struct rpc_pipe_client *cli;
745         unsigned int orig_timeout;
746         struct samr_RidTypeArray *rids = NULL;
747
748         DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain->name,
749                   sid_string_dbg(group_sid)));
750
751         if ( !winbindd_can_contact_domain( domain ) ) {
752                 DEBUG(10,("lookup_groupmem: No incoming trust for domain %s\n",
753                           domain->name));
754                 return NT_STATUS_OK;
755         }
756
757         if (!sid_peek_check_rid(&domain->sid, group_sid, &group_rid))
758                 return NT_STATUS_UNSUCCESSFUL;
759
760         *num_names = 0;
761
762         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
763         if (!NT_STATUS_IS_OK(result))
764                 return result;
765
766         result = rpccli_samr_OpenGroup(cli, mem_ctx,
767                                        &dom_pol,
768                                        des_access,
769                                        group_rid,
770                                        &group_pol);
771
772         if (!NT_STATUS_IS_OK(result))
773                 return result;
774
775         /* Step #1: Get a list of user rids that are the members of the
776            group. */
777
778         /* This call can take a long time - allow the server to time out.
779            35 seconds should do it. */
780
781         orig_timeout = rpccli_set_timeout(cli, 35000);
782
783         result = rpccli_samr_QueryGroupMember(cli, mem_ctx,
784                                               &group_pol,
785                                               &rids);
786
787         /* And restore our original timeout. */
788         rpccli_set_timeout(cli, orig_timeout);
789
790         rpccli_samr_Close(cli, mem_ctx, &group_pol);
791
792         if (!NT_STATUS_IS_OK(result))
793                 return result;
794
795         *num_names = rids->count;
796         rid_mem = rids->rids;
797
798         if (!*num_names) {
799                 names = NULL;
800                 name_types = NULL;
801                 sid_mem = NULL;
802                 return NT_STATUS_OK;
803         }
804
805         /* Step #2: Convert list of rids into list of usernames.  Do this
806            in bunches of ~1000 to avoid crashing NT4.  It looks like there
807            is a buffer overflow or something like that lurking around
808            somewhere. */
809
810 #define MAX_LOOKUP_RIDS 900
811
812         *names = TALLOC_ZERO_ARRAY(mem_ctx, char *, *num_names);
813         *name_types = TALLOC_ZERO_ARRAY(mem_ctx, uint32, *num_names);
814         *sid_mem = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, *num_names);
815
816         for (j=0;j<(*num_names);j++)
817                 sid_compose(&(*sid_mem)[j], &domain->sid, rid_mem[j]);
818
819         if (*num_names>0 && (!*names || !*name_types))
820                 return NT_STATUS_NO_MEMORY;
821
822         for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) {
823                 int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS);
824                 struct lsa_Strings tmp_names;
825                 struct samr_Ids tmp_types;
826
827                 /* Lookup a chunk of rids */
828
829                 result = rpccli_samr_LookupRids(cli, mem_ctx,
830                                                 &dom_pol,
831                                                 num_lookup_rids,
832                                                 &rid_mem[i],
833                                                 &tmp_names,
834                                                 &tmp_types);
835
836                 /* see if we have a real error (and yes the
837                    STATUS_SOME_UNMAPPED is the one returned from 2k) */
838
839                 if (!NT_STATUS_IS_OK(result) &&
840                     !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
841                         return result;
842
843                 /* Copy result into array.  The talloc system will take
844                    care of freeing the temporary arrays later on. */
845
846                 if (tmp_names.count != tmp_types.count) {
847                         return NT_STATUS_UNSUCCESSFUL;
848                 }
849
850                 for (r=0; r<tmp_names.count; r++) {
851                         if (tmp_types.ids[r] == SID_NAME_UNKNOWN) {
852                                 continue;
853                         }
854                         (*names)[total_names] = fill_domain_username_talloc(
855                                 mem_ctx, domain->name,
856                                 tmp_names.names[r].string, true);
857                         (*name_types)[total_names] = tmp_types.ids[r];
858                         total_names += 1;
859                 }
860         }
861
862         *num_names = total_names;
863
864         return NT_STATUS_OK;
865 }
866
867 #ifdef HAVE_LDAP
868
869 #include <ldap.h>
870
871 static int get_ldap_seq(const char *server, int port, uint32 *seq)
872 {
873         int ret = -1;
874         struct timeval to;
875         const char *attrs[] = {"highestCommittedUSN", NULL};
876         LDAPMessage *res = NULL;
877         char **values = NULL;
878         LDAP *ldp = NULL;
879
880         *seq = DOM_SEQUENCE_NONE;
881
882         /*
883          * Parameterised (5) second timeout on open. This is needed as the
884          * search timeout doesn't seem to apply to doing an open as well. JRA.
885          */
886
887         ldp = ldap_open_with_timeout(server, port, lp_ldap_timeout());
888         if (ldp == NULL)
889                 return -1;
890
891         /* Timeout if no response within 20 seconds. */
892         to.tv_sec = 10;
893         to.tv_usec = 0;
894
895         if (ldap_search_st(ldp, "", LDAP_SCOPE_BASE, "(objectclass=*)",
896                            CONST_DISCARD(char **, attrs), 0, &to, &res))
897                 goto done;
898
899         if (ldap_count_entries(ldp, res) != 1)
900                 goto done;
901
902         values = ldap_get_values(ldp, res, "highestCommittedUSN");
903         if (!values || !values[0])
904                 goto done;
905
906         *seq = atoi(values[0]);
907         ret = 0;
908
909   done:
910
911         if (values)
912                 ldap_value_free(values);
913         if (res)
914                 ldap_msgfree(res);
915         if (ldp)
916                 ldap_unbind(ldp);
917         return ret;
918 }
919
920 /**********************************************************************
921  Get the sequence number for a Windows AD native mode domain using
922  LDAP queries.
923 **********************************************************************/
924
925 static int get_ldap_sequence_number(struct winbindd_domain *domain, uint32 *seq)
926 {
927         int ret = -1;
928         char addr[INET6_ADDRSTRLEN];
929
930         print_sockaddr(addr, sizeof(addr), &domain->dcaddr);
931         if ((ret = get_ldap_seq(addr, LDAP_PORT, seq)) == 0) {
932                 DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence "
933                           "number for Domain (%s) from DC (%s)\n",
934                         domain->name, addr));
935         }
936         return ret;
937 }
938
939 #endif /* HAVE_LDAP */
940
941 /* find the sequence number for a domain */
942 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
943 {
944         TALLOC_CTX *mem_ctx;
945         union samr_DomainInfo *info = NULL;
946         NTSTATUS result;
947         struct policy_handle dom_pol;
948         bool got_seq_num = False;
949         struct rpc_pipe_client *cli;
950
951         DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name));
952
953         if ( !winbindd_can_contact_domain( domain ) ) {
954                 DEBUG(10,("sequence_number: No incoming trust for domain %s\n",
955                           domain->name));
956                 *seq = time(NULL);
957                 return NT_STATUS_OK;
958         }
959
960         *seq = DOM_SEQUENCE_NONE;
961
962         if (!(mem_ctx = talloc_init("sequence_number[rpc]")))
963                 return NT_STATUS_NO_MEMORY;
964
965 #ifdef HAVE_LDAP
966         if ( domain->active_directory ) 
967         {
968                 int res;
969
970                 DEBUG(8,("using get_ldap_seq() to retrieve the "
971                          "sequence number\n"));
972
973                 res =  get_ldap_sequence_number( domain, seq );
974                 if (res == 0)
975                 {                       
976                         result = NT_STATUS_OK;
977                         DEBUG(10,("domain_sequence_number: LDAP for "
978                                   "domain %s is %u\n",
979                                   domain->name, *seq));
980                         goto done;
981                 }
982
983                 DEBUG(10,("domain_sequence_number: failed to get LDAP "
984                           "sequence number for domain %s\n",
985                           domain->name ));
986         }
987 #endif /* HAVE_LDAP */
988
989         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
990         if (!NT_STATUS_IS_OK(result)) {
991                 goto done;
992         }
993
994         /* Query domain info */
995
996         result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
997                                              &dom_pol,
998                                              8,
999                                              &info);
1000
1001         if (NT_STATUS_IS_OK(result)) {
1002                 *seq = info->info8.sequence_num;
1003                 got_seq_num = True;
1004                 goto seq_num;
1005         }
1006
1007         /* retry with info-level 2 in case the dc does not support info-level 8
1008          * (like all older samba2 and samba3 dc's) - Guenther */
1009
1010         result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
1011                                              &dom_pol,
1012                                              2,
1013                                              &info);
1014
1015         if (NT_STATUS_IS_OK(result)) {
1016                 *seq = info->general.sequence_num;
1017                 got_seq_num = True;
1018         }
1019
1020  seq_num:
1021         if (got_seq_num) {
1022                 DEBUG(10,("domain_sequence_number: for domain %s is %u\n",
1023                           domain->name, (unsigned)*seq));
1024         } else {
1025                 DEBUG(10,("domain_sequence_number: failed to get sequence "
1026                           "number (%u) for domain %s\n",
1027                           (unsigned)*seq, domain->name ));
1028         }
1029
1030   done:
1031
1032         talloc_destroy(mem_ctx);
1033
1034         return result;
1035 }
1036
1037 /* get a list of trusted domains */
1038 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
1039                                 TALLOC_CTX *mem_ctx,
1040                                 uint32 *num_domains,
1041                                 char ***names,
1042                                 char ***alt_names,
1043                                 DOM_SID **dom_sids)
1044 {
1045         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1046         uint32 enum_ctx = 0;
1047         struct rpc_pipe_client *cli;
1048         struct policy_handle lsa_policy;
1049
1050         DEBUG(3,("rpc: trusted_domains\n"));
1051
1052         *num_domains = 0;
1053         *names = NULL;
1054         *alt_names = NULL;
1055         *dom_sids = NULL;
1056
1057         result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
1058         if (!NT_STATUS_IS_OK(result))
1059                 return result;
1060
1061         result = STATUS_MORE_ENTRIES;
1062
1063         while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
1064                 uint32 start_idx;
1065                 int i;
1066                 struct lsa_DomainList dom_list;
1067
1068                 result = rpccli_lsa_EnumTrustDom(cli, mem_ctx,
1069                                                  &lsa_policy,
1070                                                  &enum_ctx,
1071                                                  &dom_list,
1072                                                  (uint32_t)-1);
1073
1074                 if (!NT_STATUS_IS_OK(result) &&
1075                     !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
1076                         break;
1077
1078                 start_idx = *num_domains;
1079                 *num_domains += dom_list.count;
1080                 *names = TALLOC_REALLOC_ARRAY(mem_ctx, *names,
1081                                               char *, *num_domains);
1082                 *dom_sids = TALLOC_REALLOC_ARRAY(mem_ctx, *dom_sids,
1083                                                  DOM_SID, *num_domains);
1084                 *alt_names = TALLOC_REALLOC_ARRAY(mem_ctx, *alt_names,
1085                                                  char *, *num_domains);
1086                 if ((*names == NULL) || (*dom_sids == NULL) ||
1087                     (*alt_names == NULL))
1088                         return NT_STATUS_NO_MEMORY;
1089
1090                 for (i=0; i<dom_list.count; i++) {
1091                         (*names)[start_idx+i] = CONST_DISCARD(char *, dom_list.domains[i].name.string);
1092                         (*dom_sids)[start_idx+i] = *dom_list.domains[i].sid;
1093                         (*alt_names)[start_idx+i] = talloc_strdup(mem_ctx, "");
1094                 }
1095         }
1096         return result;
1097 }
1098
1099 /* find the lockout policy for a domain */
1100 static NTSTATUS msrpc_lockout_policy(struct winbindd_domain *domain,
1101                                      TALLOC_CTX *mem_ctx,
1102                                      struct samr_DomInfo12 *lockout_policy)
1103 {
1104         NTSTATUS result;
1105         struct rpc_pipe_client *cli;
1106         struct policy_handle dom_pol;
1107         union samr_DomainInfo *info = NULL;
1108
1109         DEBUG(10,("rpc: fetch lockout policy for %s\n", domain->name));
1110
1111         if ( !winbindd_can_contact_domain( domain ) ) {
1112                 DEBUG(10,("msrpc_lockout_policy: No incoming trust for domain %s\n",
1113                           domain->name));
1114                 return NT_STATUS_NOT_SUPPORTED;
1115         }
1116
1117         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
1118         if (!NT_STATUS_IS_OK(result)) {
1119                 goto done;
1120         }
1121
1122         result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
1123                                              &dom_pol,
1124                                              12,
1125                                              &info);
1126         if (!NT_STATUS_IS_OK(result)) {
1127                 goto done;
1128         }
1129
1130         *lockout_policy = info->info12;
1131
1132         DEBUG(10,("msrpc_lockout_policy: lockout_threshold %d\n",
1133                 info->info12.lockout_threshold));
1134
1135   done:
1136
1137         return result;
1138 }
1139
1140 /* find the password policy for a domain */
1141 static NTSTATUS msrpc_password_policy(struct winbindd_domain *domain,
1142                                       TALLOC_CTX *mem_ctx,
1143                                       struct samr_DomInfo1 *password_policy)
1144 {
1145         NTSTATUS result;
1146         struct rpc_pipe_client *cli;
1147         struct policy_handle dom_pol;
1148         union samr_DomainInfo *info = NULL;
1149
1150         DEBUG(10,("rpc: fetch password policy for %s\n", domain->name));
1151
1152         if ( !winbindd_can_contact_domain( domain ) ) {
1153                 DEBUG(10,("msrpc_password_policy: No incoming trust for domain %s\n",
1154                           domain->name));
1155                 return NT_STATUS_NOT_SUPPORTED;
1156         }
1157
1158         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
1159         if (!NT_STATUS_IS_OK(result)) {
1160                 goto done;
1161         }
1162
1163         result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
1164                                              &dom_pol,
1165                                              1,
1166                                              &info);
1167         if (!NT_STATUS_IS_OK(result)) {
1168                 goto done;
1169         }
1170
1171         *password_policy = info->info1;
1172
1173         DEBUG(10,("msrpc_password_policy: min_length_password %d\n",
1174                 info->info1.min_password_length));
1175
1176   done:
1177
1178         return result;
1179 }
1180
1181 typedef NTSTATUS (*lookup_sids_fn_t)(struct rpc_pipe_client *cli,
1182                                      TALLOC_CTX *mem_ctx,
1183                                      struct policy_handle *pol,
1184                                      int num_sids,
1185                                      const DOM_SID *sids,
1186                                      char ***pdomains,
1187                                      char ***pnames,
1188                                      enum lsa_SidType **ptypes);
1189
1190 NTSTATUS winbindd_lookup_sids(TALLOC_CTX *mem_ctx,
1191                               struct winbindd_domain *domain,
1192                               uint32_t num_sids,
1193                               const struct dom_sid *sids,
1194                               char ***domains,
1195                               char ***names,
1196                               enum lsa_SidType **types)
1197 {
1198         NTSTATUS status;
1199         struct rpc_pipe_client *cli = NULL;
1200         struct policy_handle lsa_policy;
1201         unsigned int orig_timeout;
1202         lookup_sids_fn_t lookup_sids_fn = rpccli_lsa_lookup_sids;
1203
1204         if (domain->can_do_ncacn_ip_tcp) {
1205                 status = cm_connect_lsa_tcp(domain, mem_ctx, &cli);
1206                 if (NT_STATUS_IS_OK(status)) {
1207                         lookup_sids_fn = rpccli_lsa_lookup_sids3;
1208                         goto lookup;
1209                 }
1210                 domain->can_do_ncacn_ip_tcp = false;
1211         }
1212         status = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
1213
1214         if (!NT_STATUS_IS_OK(status)) {
1215                 return status;
1216         }
1217
1218  lookup:
1219         /*
1220          * This call can take a long time
1221          * allow the server to time out.
1222          * 35 seconds should do it.
1223          */
1224         orig_timeout = rpccli_set_timeout(cli, 35000);
1225
1226         status = lookup_sids_fn(cli,
1227                                 mem_ctx,
1228                                 &lsa_policy,
1229                                 num_sids,
1230                                 sids,
1231                                 domains,
1232                                 names,
1233                                 types);
1234
1235         /* And restore our original timeout. */
1236         rpccli_set_timeout(cli, orig_timeout);
1237
1238         if (!NT_STATUS_IS_OK(status)) {
1239                 return status;
1240         }
1241
1242         return status;
1243 }
1244
1245 typedef NTSTATUS (*lookup_names_fn_t)(struct rpc_pipe_client *cli,
1246                                       TALLOC_CTX *mem_ctx,
1247                                       struct policy_handle *pol,
1248                                       int num_names,
1249                                       const char **names,
1250                                       const char ***dom_names,
1251                                       int level,
1252                                       struct dom_sid **sids,
1253                                       enum lsa_SidType **types);
1254
1255 NTSTATUS winbindd_lookup_names(TALLOC_CTX *mem_ctx,
1256                                struct winbindd_domain *domain,
1257                                uint32_t num_names,
1258                                const char **names,
1259                                const char ***domains,
1260                                struct dom_sid **sids,
1261                                enum lsa_SidType **types)
1262 {
1263         NTSTATUS status;
1264         struct rpc_pipe_client *cli = NULL;
1265         struct policy_handle lsa_policy;
1266         unsigned int orig_timeout;
1267         lookup_names_fn_t lookup_names_fn = rpccli_lsa_lookup_names;
1268
1269         if (domain->can_do_ncacn_ip_tcp) {
1270                 status = cm_connect_lsa_tcp(domain, mem_ctx, &cli);
1271                 if (NT_STATUS_IS_OK(status)) {
1272                         lookup_names_fn = rpccli_lsa_lookup_names4;
1273                         goto lookup;
1274                 }
1275                 domain->can_do_ncacn_ip_tcp = false;
1276         }
1277         status = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
1278
1279         if (!NT_STATUS_IS_OK(status)) {
1280                 return status;
1281         }
1282
1283  lookup:
1284
1285         /*
1286          * This call can take a long time
1287          * allow the server to time out.
1288          * 35 seconds should do it.
1289          */
1290         orig_timeout = rpccli_set_timeout(cli, 35000);
1291
1292         status = lookup_names_fn(cli,
1293                                  mem_ctx,
1294                                  &lsa_policy,
1295                                  num_names,
1296                                  (const char **) names,
1297                                  domains,
1298                                  1,
1299                                  sids,
1300                                  types);
1301
1302         /* And restore our original timeout. */
1303         rpccli_set_timeout(cli, orig_timeout);
1304
1305         if (!NT_STATUS_IS_OK(status)) {
1306                 return status;
1307         }
1308
1309         return status;
1310 }
1311
1312 /* the rpc backend methods are exposed via this structure */
1313 struct winbindd_methods msrpc_methods = {
1314         False,
1315         query_user_list,
1316         enum_dom_groups,
1317         enum_local_groups,
1318         msrpc_name_to_sid,
1319         msrpc_sid_to_name,
1320         msrpc_rids_to_names,
1321         query_user,
1322         lookup_usergroups,
1323         msrpc_lookup_useraliases,
1324         lookup_groupmem,
1325         sequence_number,
1326         msrpc_lockout_policy,
1327         msrpc_password_policy,
1328         trusted_domains,
1329 };