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