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