Use rpccli_samr_OpenGroup() all over the place.
[metze/samba/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    
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 = NULL;
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         if ( !winbindd_can_contact_domain( domain ) ) {
460                 DEBUG(10,("query_user: No incoming trust for domain %s\n",
461                           domain->name));
462                 return NT_STATUS_OK;
463         }
464         
465         /* no cache; hit the wire */
466                 
467         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
468         if (!NT_STATUS_IS_OK(result))
469                 return result;
470
471         /* Get user handle */
472         result = rpccli_samr_open_user(cli, mem_ctx, &dom_pol,
473                                        SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid,
474                                        &user_pol);
475
476         if (!NT_STATUS_IS_OK(result))
477                 return result;
478
479         /* Get user info */
480         result = rpccli_samr_query_userinfo(cli, mem_ctx, &user_pol,
481                                             0x15, &ctr);
482
483         rpccli_samr_Close(cli, mem_ctx, &user_pol);
484
485         if (!NT_STATUS_IS_OK(result))
486                 return result;
487
488         sid_compose(&user_info->user_sid, &domain->sid, user_rid);
489         sid_compose(&user_info->group_sid, &domain->sid,
490                     ctr->info.id21->group_rid);
491         user_info->acct_name = unistr2_to_ascii_talloc(mem_ctx, 
492                                             &ctr->info.id21->uni_user_name);
493         user_info->full_name = unistr2_to_ascii_talloc(mem_ctx, 
494                                             &ctr->info.id21->uni_full_name);
495         user_info->homedir = NULL;
496         user_info->shell = NULL;
497         user_info->primary_gid = (gid_t)-1;
498
499         return NT_STATUS_OK;
500 }                                   
501
502 /* Lookup groups a user is a member of.  I wish Unix had a call like this! */
503 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
504                                   TALLOC_CTX *mem_ctx,
505                                   const DOM_SID *user_sid,
506                                   uint32 *num_groups, DOM_SID **user_grpsids)
507 {
508         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
509         POLICY_HND dom_pol, user_pol;
510         uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
511         DOM_GID *user_groups;
512         unsigned int i;
513         uint32 user_rid;
514         struct rpc_pipe_client *cli;
515
516         DEBUG(3,("rpc: lookup_usergroups sid=%s\n", sid_string_dbg(user_sid)));
517
518         if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
519                 return NT_STATUS_UNSUCCESSFUL;
520
521         *num_groups = 0;
522         *user_grpsids = NULL;
523
524         /* so lets see if we have a cached user_info_3 */
525         result = lookup_usergroups_cached(domain, mem_ctx, user_sid, 
526                                           num_groups, user_grpsids);
527
528         if (NT_STATUS_IS_OK(result)) {
529                 return NT_STATUS_OK;
530         }
531
532         if ( !winbindd_can_contact_domain( domain ) ) {
533                 DEBUG(10,("lookup_usergroups: No incoming trust for domain %s\n",
534                           domain->name));
535
536                 /* Tell the cache manager not to remember this one */
537
538                 return NT_STATUS_SYNCHRONIZATION_REQUIRED;
539         }
540
541         /* no cache; hit the wire */
542         
543         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
544         if (!NT_STATUS_IS_OK(result))
545                 return result;
546
547         /* Get user handle */
548         result = rpccli_samr_open_user(cli, mem_ctx, &dom_pol,
549                                         des_access, user_rid, &user_pol);
550
551         if (!NT_STATUS_IS_OK(result))
552                 return result;
553
554         /* Query user rids */
555         result = rpccli_samr_query_usergroups(cli, mem_ctx, &user_pol, 
556                                            num_groups, &user_groups);
557
558         rpccli_samr_Close(cli, mem_ctx, &user_pol);
559
560         if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0)
561                 return result;
562
563         (*user_grpsids) = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_groups);
564         if (!(*user_grpsids))
565                 return NT_STATUS_NO_MEMORY;
566
567         for (i=0;i<(*num_groups);i++) {
568                 sid_copy(&((*user_grpsids)[i]), &domain->sid);
569                 sid_append_rid(&((*user_grpsids)[i]),
570                                 user_groups[i].g_rid);
571         }
572         
573         return NT_STATUS_OK;
574 }
575
576 NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain,
577                                   TALLOC_CTX *mem_ctx,
578                                   uint32 num_sids, const DOM_SID *sids,
579                                   uint32 *num_aliases, uint32 **alias_rids)
580 {
581         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
582         POLICY_HND dom_pol;
583         DOM_SID2 *query_sids;
584         uint32 num_query_sids = 0;
585         int i;
586         struct rpc_pipe_client *cli;
587         uint32 *alias_rids_query, num_aliases_query;
588         int rangesize = MAX_SAM_ENTRIES_W2K;
589         uint32 total_sids = 0;
590         int num_queries = 1;
591
592         *num_aliases = 0;
593         *alias_rids = NULL;
594
595         DEBUG(3,("rpc: lookup_useraliases\n"));
596
597         if ( !winbindd_can_contact_domain( domain ) ) {
598                 DEBUG(10,("msrpc_lookup_useraliases: No incoming trust for domain %s\n",
599                           domain->name));
600                 return NT_STATUS_OK;
601         }
602
603         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
604         if (!NT_STATUS_IS_OK(result))
605                 return result;
606
607         do {
608                 /* prepare query */
609
610                 num_query_sids = MIN(num_sids - total_sids, rangesize);
611
612                 DEBUG(10,("rpc: lookup_useraliases: entering query %d for %d sids\n", 
613                         num_queries, num_query_sids));  
614
615                 if (num_query_sids) {
616                         query_sids = TALLOC_ARRAY(mem_ctx, DOM_SID2, num_query_sids);
617                         if (query_sids == NULL) {
618                                 return NT_STATUS_NO_MEMORY;
619                         }
620                 } else {
621                         query_sids = NULL;
622                 }
623
624                 for (i=0; i<num_query_sids; i++) {
625                         sid_copy(&query_sids[i].sid, &sids[total_sids++]);
626                         query_sids[i].num_auths = query_sids[i].sid.num_auths;
627                 }
628
629                 /* do request */
630
631                 result = rpccli_samr_query_useraliases(cli, mem_ctx, &dom_pol,
632                                                        num_query_sids, query_sids,
633                                                        &num_aliases_query, 
634                                                        &alias_rids_query);
635
636                 if (!NT_STATUS_IS_OK(result)) {
637                         *num_aliases = 0;
638                         *alias_rids = NULL;
639                         TALLOC_FREE(query_sids);
640                         goto done;
641                 }
642
643                 /* process output */
644
645                 for (i=0; i<num_aliases_query; i++) {
646                         size_t na = *num_aliases;
647                         if (!add_rid_to_array_unique(mem_ctx, alias_rids_query[i], 
648                                                 alias_rids, &na)) {
649                                 return NT_STATUS_NO_MEMORY;
650                         }
651                         *num_aliases = na;
652                 }
653
654                 TALLOC_FREE(query_sids);
655
656                 num_queries++;
657
658         } while (total_sids < num_sids);
659
660  done:
661         DEBUG(10,("rpc: lookup_useraliases: got %d aliases in %d queries "
662                 "(rangesize: %d)\n", *num_aliases, num_queries, rangesize));
663
664         return result;
665 }
666
667
668 /* Lookup group membership given a rid.   */
669 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
670                                 TALLOC_CTX *mem_ctx,
671                                 const DOM_SID *group_sid, uint32 *num_names, 
672                                 DOM_SID **sid_mem, char ***names, 
673                                 uint32 **name_types)
674 {
675         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
676         uint32 i, total_names = 0;
677         POLICY_HND dom_pol, group_pol;
678         uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
679         uint32 *rid_mem = NULL;
680         uint32 group_rid;
681         unsigned int j;
682         struct rpc_pipe_client *cli;
683         unsigned int orig_timeout;
684
685         DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain->name,
686                   sid_string_dbg(group_sid)));
687
688         if ( !winbindd_can_contact_domain( domain ) ) {
689                 DEBUG(10,("lookup_groupmem: No incoming trust for domain %s\n",
690                           domain->name));
691                 return NT_STATUS_OK;
692         }
693
694         if (!sid_peek_check_rid(&domain->sid, group_sid, &group_rid))
695                 return NT_STATUS_UNSUCCESSFUL;
696
697         *num_names = 0;
698
699         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
700         if (!NT_STATUS_IS_OK(result))
701                 return result;
702
703         result = rpccli_samr_OpenGroup(cli, mem_ctx,
704                                        &dom_pol,
705                                        des_access,
706                                        group_rid,
707                                        &group_pol);
708
709         if (!NT_STATUS_IS_OK(result))
710                 return result;
711
712         /* Step #1: Get a list of user rids that are the members of the
713            group. */
714
715         /* This call can take a long time - allow the server to time out.
716            35 seconds should do it. */
717
718         orig_timeout = cli_set_timeout(cli->cli, 35000);
719
720         result = rpccli_samr_query_groupmem(cli, mem_ctx,
721                                             &group_pol, num_names, &rid_mem,
722                                             name_types);
723
724         /* And restore our original timeout. */
725         cli_set_timeout(cli->cli, orig_timeout);
726
727         rpccli_samr_Close(cli, mem_ctx, &group_pol);
728
729         if (!NT_STATUS_IS_OK(result))
730                 return result;
731
732         if (!*num_names) {
733                 names = NULL;
734                 name_types = NULL;
735                 sid_mem = NULL;
736                 return NT_STATUS_OK;
737         }
738
739         /* Step #2: Convert list of rids into list of usernames.  Do this
740            in bunches of ~1000 to avoid crashing NT4.  It looks like there
741            is a buffer overflow or something like that lurking around
742            somewhere. */
743
744 #define MAX_LOOKUP_RIDS 900
745
746         *names = TALLOC_ZERO_ARRAY(mem_ctx, char *, *num_names);
747         *name_types = TALLOC_ZERO_ARRAY(mem_ctx, uint32, *num_names);
748         *sid_mem = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, *num_names);
749
750         for (j=0;j<(*num_names);j++)
751                 sid_compose(&(*sid_mem)[j], &domain->sid, rid_mem[j]);
752         
753         if (*num_names>0 && (!*names || !*name_types))
754                 return NT_STATUS_NO_MEMORY;
755
756         for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) {
757                 int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS);
758                 uint32 tmp_num_names = 0;
759                 char **tmp_names = NULL;
760                 uint32 *tmp_types = NULL;
761
762                 /* Lookup a chunk of rids */
763
764                 result = rpccli_samr_lookup_rids(cli, mem_ctx,
765                                                  &dom_pol,
766                                                  num_lookup_rids,
767                                                  &rid_mem[i],
768                                                  &tmp_num_names,
769                                                  &tmp_names, &tmp_types);
770
771                 /* see if we have a real error (and yes the
772                    STATUS_SOME_UNMAPPED is the one returned from 2k) */
773                 
774                 if (!NT_STATUS_IS_OK(result) &&
775                     !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
776                         return result;
777                         
778                 /* Copy result into array.  The talloc system will take
779                    care of freeing the temporary arrays later on. */
780
781                 memcpy(&(*names)[i], tmp_names, sizeof(char *) * 
782                        tmp_num_names);
783
784                 memcpy(&(*name_types)[i], tmp_types, sizeof(uint32) *
785                        tmp_num_names);
786                 
787                 total_names += tmp_num_names;
788         }
789
790         *num_names = total_names;
791
792         return NT_STATUS_OK;
793 }
794
795 #ifdef HAVE_LDAP
796
797 #include <ldap.h>
798
799 static int get_ldap_seq(const char *server, int port, uint32 *seq)
800 {
801         int ret = -1;
802         struct timeval to;
803         const char *attrs[] = {"highestCommittedUSN", NULL};
804         LDAPMessage *res = NULL;
805         char **values = NULL;
806         LDAP *ldp = NULL;
807
808         *seq = DOM_SEQUENCE_NONE;
809
810         /*
811          * Parameterised (5) second timeout on open. This is needed as the
812          * search timeout doesn't seem to apply to doing an open as well. JRA.
813          */
814
815         ldp = ldap_open_with_timeout(server, port, lp_ldap_timeout());
816         if (ldp == NULL)
817                 return -1;
818
819         /* Timeout if no response within 20 seconds. */
820         to.tv_sec = 10;
821         to.tv_usec = 0;
822
823         if (ldap_search_st(ldp, "", LDAP_SCOPE_BASE, "(objectclass=*)",
824                            CONST_DISCARD(char **, attrs), 0, &to, &res))
825                 goto done;
826
827         if (ldap_count_entries(ldp, res) != 1)
828                 goto done;
829
830         values = ldap_get_values(ldp, res, "highestCommittedUSN");
831         if (!values || !values[0])
832                 goto done;
833
834         *seq = atoi(values[0]);
835         ret = 0;
836
837   done:
838
839         if (values)
840                 ldap_value_free(values);
841         if (res)
842                 ldap_msgfree(res);
843         if (ldp)
844                 ldap_unbind(ldp);
845         return ret;
846 }
847
848 /**********************************************************************
849  Get the sequence number for a Windows AD native mode domain using
850  LDAP queries.
851 **********************************************************************/
852
853 static int get_ldap_sequence_number(struct winbindd_domain *domain, uint32 *seq)
854 {
855         int ret = -1;
856         char addr[INET6_ADDRSTRLEN];
857
858         print_sockaddr(addr, sizeof(addr), &domain->dcaddr);
859         if ((ret = get_ldap_seq(addr, LDAP_PORT, seq)) == 0) {
860                 DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence "
861                           "number for Domain (%s) from DC (%s)\n",
862                         domain->name, addr));
863         }
864         return ret;
865 }
866
867 #endif /* HAVE_LDAP */
868
869 /* find the sequence number for a domain */
870 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
871 {
872         TALLOC_CTX *mem_ctx;
873         SAM_UNK_CTR ctr;
874         NTSTATUS result;
875         POLICY_HND dom_pol;
876         bool got_seq_num = False;
877         struct rpc_pipe_client *cli;
878
879         DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name));
880
881         if ( !winbindd_can_contact_domain( domain ) ) {
882                 DEBUG(10,("sequence_number: No incoming trust for domain %s\n",
883                           domain->name));
884                 *seq = time(NULL);
885                 return NT_STATUS_OK;
886         }
887
888         *seq = DOM_SEQUENCE_NONE;
889
890         if (!(mem_ctx = talloc_init("sequence_number[rpc]")))
891                 return NT_STATUS_NO_MEMORY;
892
893 #ifdef HAVE_LDAP
894         if ( domain->active_directory ) 
895         {
896                 int res;
897
898                 DEBUG(8,("using get_ldap_seq() to retrieve the "
899                          "sequence number\n"));
900
901                 res =  get_ldap_sequence_number( domain, seq );
902                 if (res == 0)
903                 {                       
904                         result = NT_STATUS_OK;
905                         DEBUG(10,("domain_sequence_number: LDAP for "
906                                   "domain %s is %u\n",
907                                   domain->name, *seq));
908                         goto done;
909                 }
910
911                 DEBUG(10,("domain_sequence_number: failed to get LDAP "
912                           "sequence number for domain %s\n",
913                           domain->name ));
914         }
915 #endif /* HAVE_LDAP */
916
917         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
918         if (!NT_STATUS_IS_OK(result)) {
919                 goto done;
920         }
921
922         /* Query domain info */
923
924         result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 8, &ctr);
925
926         if (NT_STATUS_IS_OK(result)) {
927                 *seq = ctr.info.inf8.seq_num;
928                 got_seq_num = True;
929                 goto seq_num;
930         }
931
932         /* retry with info-level 2 in case the dc does not support info-level 8
933          * (like all older samba2 and samba3 dc's - Guenther */
934
935         result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 2, &ctr);
936         
937         if (NT_STATUS_IS_OK(result)) {
938                 *seq = ctr.info.inf2.seq_num;
939                 got_seq_num = True;
940         }
941
942  seq_num:
943         if (got_seq_num) {
944                 DEBUG(10,("domain_sequence_number: for domain %s is %u\n",
945                           domain->name, (unsigned)*seq));
946         } else {
947                 DEBUG(10,("domain_sequence_number: failed to get sequence "
948                           "number (%u) for domain %s\n",
949                           (unsigned)*seq, domain->name ));
950         }
951
952   done:
953
954         talloc_destroy(mem_ctx);
955
956         return result;
957 }
958
959 /* get a list of trusted domains */
960 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
961                                 TALLOC_CTX *mem_ctx,
962                                 uint32 *num_domains,
963                                 char ***names,
964                                 char ***alt_names,
965                                 DOM_SID **dom_sids)
966 {
967         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
968         uint32 enum_ctx = 0;
969         struct rpc_pipe_client *cli;
970         POLICY_HND lsa_policy;
971
972         DEBUG(3,("rpc: trusted_domains\n"));
973
974         *num_domains = 0;
975         *names = NULL;
976         *alt_names = NULL;
977         *dom_sids = NULL;
978
979         result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
980         if (!NT_STATUS_IS_OK(result))
981                 return result;
982
983         result = STATUS_MORE_ENTRIES;
984
985         while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
986                 uint32 start_idx, num;
987                 char **tmp_names;
988                 DOM_SID *tmp_sids;
989                 int i;
990
991                 result = rpccli_lsa_enum_trust_dom(cli, mem_ctx,
992                                                    &lsa_policy, &enum_ctx,
993                                                    &num, &tmp_names,
994                                                    &tmp_sids);
995
996                 if (!NT_STATUS_IS_OK(result) &&
997                     !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
998                         break;
999
1000                 start_idx = *num_domains;
1001                 *num_domains += num;
1002                 *names = TALLOC_REALLOC_ARRAY(mem_ctx, *names,
1003                                               char *, *num_domains);
1004                 *dom_sids = TALLOC_REALLOC_ARRAY(mem_ctx, *dom_sids,
1005                                                  DOM_SID, *num_domains);
1006                 *alt_names = TALLOC_REALLOC_ARRAY(mem_ctx, *alt_names,
1007                                                  char *, *num_domains);
1008                 if ((*names == NULL) || (*dom_sids == NULL) ||
1009                     (*alt_names == NULL))
1010                         return NT_STATUS_NO_MEMORY;
1011
1012                 for (i=0; i<num; i++) {
1013                         (*names)[start_idx+i] = tmp_names[i];
1014                         (*dom_sids)[start_idx+i] = tmp_sids[i];
1015                         (*alt_names)[start_idx+i] = talloc_strdup(mem_ctx, "");
1016                 }
1017         }
1018         return result;
1019 }
1020
1021 /* find the lockout policy for a domain */
1022 NTSTATUS msrpc_lockout_policy(struct winbindd_domain *domain, 
1023                               TALLOC_CTX *mem_ctx,
1024                               SAM_UNK_INFO_12 *lockout_policy)
1025 {
1026         NTSTATUS result;
1027         struct rpc_pipe_client *cli;
1028         POLICY_HND dom_pol;
1029         SAM_UNK_CTR ctr;
1030
1031         DEBUG(10,("rpc: fetch lockout policy for %s\n", domain->name));
1032
1033         if ( !winbindd_can_contact_domain( domain ) ) {
1034                 DEBUG(10,("msrpc_lockout_policy: No incoming trust for domain %s\n",
1035                           domain->name));
1036                 return NT_STATUS_NOT_SUPPORTED;
1037         }
1038
1039         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
1040         if (!NT_STATUS_IS_OK(result)) {
1041                 goto done;
1042         }
1043
1044         result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 12, &ctr);
1045         if (!NT_STATUS_IS_OK(result)) {
1046                 goto done;
1047         }
1048
1049         *lockout_policy = ctr.info.inf12;
1050
1051         DEBUG(10,("msrpc_lockout_policy: bad_attempt_lockout %d\n", 
1052                 ctr.info.inf12.bad_attempt_lockout));
1053
1054   done:
1055
1056         return result;
1057 }
1058
1059 /* find the password policy for a domain */
1060 NTSTATUS msrpc_password_policy(struct winbindd_domain *domain, 
1061                                TALLOC_CTX *mem_ctx,
1062                                SAM_UNK_INFO_1 *password_policy)
1063 {
1064         NTSTATUS result;
1065         struct rpc_pipe_client *cli;
1066         POLICY_HND dom_pol;
1067         SAM_UNK_CTR ctr;
1068
1069         DEBUG(10,("rpc: fetch password policy for %s\n", domain->name));
1070
1071         if ( !winbindd_can_contact_domain( domain ) ) {
1072                 DEBUG(10,("msrpc_password_policy: No incoming trust for domain %s\n",
1073                           domain->name));
1074                 return NT_STATUS_NOT_SUPPORTED;
1075         }
1076
1077         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
1078         if (!NT_STATUS_IS_OK(result)) {
1079                 goto done;
1080         }
1081
1082         result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 1, &ctr);
1083         if (!NT_STATUS_IS_OK(result)) {
1084                 goto done;
1085         }
1086
1087         *password_policy = ctr.info.inf1;
1088
1089         DEBUG(10,("msrpc_password_policy: min_length_password %d\n", 
1090                 ctr.info.inf1.min_length_password));
1091
1092   done:
1093
1094         return result;
1095 }
1096
1097
1098 /* the rpc backend methods are exposed via this structure */
1099 struct winbindd_methods msrpc_methods = {
1100         False,
1101         query_user_list,
1102         enum_dom_groups,
1103         enum_local_groups,
1104         msrpc_name_to_sid,
1105         msrpc_sid_to_name,
1106         msrpc_rids_to_names,
1107         query_user,
1108         lookup_usergroups,
1109         msrpc_lookup_useraliases,
1110         lookup_groupmem,
1111         sequence_number,
1112         msrpc_lockout_policy,
1113         msrpc_password_policy,
1114         trusted_domains,
1115 };