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