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