This adds support in Winbindd's "security = ads"-mode to retrieve the POSIX
[metze/old/v3-2-winbind-ndr.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         uint32 *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", name?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, &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 = (enum SID_NAME_USE)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         NET_USER_INFO_3 *user;
416         struct rpc_pipe_client *cli;
417
418         DEBUG(3,("rpc: lookup_usergroups sid=%s\n",
419                  sid_to_string(sid_string, user_sid)));
420
421         if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
422                 return NT_STATUS_UNSUCCESSFUL;
423
424         *num_groups = 0;
425         *user_grpsids = NULL;
426
427         /* so lets see if we have a cached user_info_3 */
428         
429         if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL )
430         {
431                 DEBUG(5,("query_user: Cache lookup succeeded for %s\n", 
432                         sid_string_static(user_sid)));
433                         
434                 *num_groups = user->num_groups;
435                                 
436                 (*user_grpsids) = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_groups);
437                 for (i=0;i<(*num_groups);i++) {
438                         sid_copy(&((*user_grpsids)[i]), &domain->sid);
439                         sid_append_rid(&((*user_grpsids)[i]),
440                                        user->gids[i].g_rid);
441                 }
442                                 
443                 SAFE_FREE(user);
444                                 
445                 return NT_STATUS_OK;
446         }
447
448         /* no cache; hit the wire */
449         
450         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
451         if (!NT_STATUS_IS_OK(result))
452                 return result;
453
454         /* Get user handle */
455         result = rpccli_samr_open_user(cli, mem_ctx, &dom_pol,
456                                         des_access, user_rid, &user_pol);
457
458         if (!NT_STATUS_IS_OK(result))
459                 return result;
460
461         /* Query user rids */
462         result = rpccli_samr_query_usergroups(cli, mem_ctx, &user_pol, 
463                                            num_groups, &user_groups);
464
465         rpccli_samr_close(cli, mem_ctx, &user_pol);
466
467         if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0)
468                 return result;
469
470         (*user_grpsids) = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_groups);
471         if (!(*user_grpsids))
472                 return NT_STATUS_NO_MEMORY;
473
474         for (i=0;i<(*num_groups);i++) {
475                 sid_copy(&((*user_grpsids)[i]), &domain->sid);
476                 sid_append_rid(&((*user_grpsids)[i]),
477                                 user_groups[i].g_rid);
478         }
479         
480         return NT_STATUS_OK;
481 }
482
483 NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain,
484                                   TALLOC_CTX *mem_ctx,
485                                   uint32 num_sids, const DOM_SID *sids,
486                                   uint32 *num_aliases, uint32 **alias_rids)
487 {
488         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
489         POLICY_HND dom_pol;
490         DOM_SID2 *sid2;
491         int i;
492         struct rpc_pipe_client *cli;
493
494         *num_aliases = 0;
495         *alias_rids = NULL;
496
497         DEBUG(3,("rpc: lookup_useraliases\n"));
498
499         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
500         if (!NT_STATUS_IS_OK(result))
501                 return result;
502
503         sid2 = TALLOC_ARRAY(mem_ctx, DOM_SID2, num_sids);
504
505         if (sid2 == NULL)
506                 return NT_STATUS_NO_MEMORY;
507
508         for (i=0; i<num_sids; i++) {
509                 sid_copy(&sid2[i].sid, &sids[i]);
510                 sid2[i].num_auths = sid2[i].sid.num_auths;
511         }
512
513         result = rpccli_samr_query_useraliases(cli, mem_ctx, &dom_pol,
514                                                num_sids, sid2,
515                                                num_aliases, alias_rids);
516
517         return result;
518 }
519
520
521 /* Lookup group membership given a rid.   */
522 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
523                                 TALLOC_CTX *mem_ctx,
524                                 const DOM_SID *group_sid, uint32 *num_names, 
525                                 DOM_SID **sid_mem, char ***names, 
526                                 uint32 **name_types)
527 {
528         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
529         uint32 i, total_names = 0;
530         POLICY_HND dom_pol, group_pol;
531         uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
532         uint32 *rid_mem = NULL;
533         uint32 group_rid;
534         unsigned int j;
535         fstring sid_string;
536         struct rpc_pipe_client *cli;
537
538         DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain->name,
539                   sid_to_string(sid_string, group_sid)));
540
541         if (!sid_peek_check_rid(&domain->sid, group_sid, &group_rid))
542                 return NT_STATUS_UNSUCCESSFUL;
543
544         *num_names = 0;
545
546         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
547         if (!NT_STATUS_IS_OK(result))
548                 return result;
549
550         result = rpccli_samr_open_group(cli, mem_ctx, &dom_pol,
551                                         des_access, group_rid, &group_pol);
552
553         if (!NT_STATUS_IS_OK(result))
554                 return result;
555
556         /* Step #1: Get a list of user rids that are the members of the
557            group. */
558
559         result = rpccli_samr_query_groupmem(cli, mem_ctx,
560                                             &group_pol, num_names, &rid_mem,
561                                             name_types);
562
563         rpccli_samr_close(cli, mem_ctx, &group_pol);
564
565         if (!NT_STATUS_IS_OK(result))
566                 return result;
567
568         if (!*num_names) {
569                 names = NULL;
570                 name_types = NULL;
571                 sid_mem = NULL;
572                 return NT_STATUS_OK;
573         }
574
575         /* Step #2: Convert list of rids into list of usernames.  Do this
576            in bunches of ~1000 to avoid crashing NT4.  It looks like there
577            is a buffer overflow or something like that lurking around
578            somewhere. */
579
580 #define MAX_LOOKUP_RIDS 900
581
582         *names = TALLOC_ZERO_ARRAY(mem_ctx, char *, *num_names);
583         *name_types = TALLOC_ZERO_ARRAY(mem_ctx, uint32, *num_names);
584         *sid_mem = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, *num_names);
585
586         for (j=0;j<(*num_names);j++)
587                 sid_compose(&(*sid_mem)[j], &domain->sid, rid_mem[j]);
588         
589         if (*num_names>0 && (!*names || !*name_types))
590                 return NT_STATUS_NO_MEMORY;
591
592         for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) {
593                 int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS);
594                 uint32 tmp_num_names = 0;
595                 char **tmp_names = NULL;
596                 uint32 *tmp_types = NULL;
597
598                 /* Lookup a chunk of rids */
599
600                 result = rpccli_samr_lookup_rids(cli, mem_ctx,
601                                                  &dom_pol,
602                                                  num_lookup_rids,
603                                                  &rid_mem[i],
604                                                  &tmp_num_names,
605                                                  &tmp_names, &tmp_types);
606
607                 /* see if we have a real error (and yes the
608                    STATUS_SOME_UNMAPPED is the one returned from 2k) */
609                 
610                 if (!NT_STATUS_IS_OK(result) &&
611                     !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
612                         return result;
613                         
614                 /* Copy result into array.  The talloc system will take
615                    care of freeing the temporary arrays later on. */
616
617                 memcpy(&(*names)[i], tmp_names, sizeof(char *) * 
618                        tmp_num_names);
619
620                 memcpy(&(*name_types)[i], tmp_types, sizeof(uint32) *
621                        tmp_num_names);
622                 
623                 total_names += tmp_num_names;
624         }
625
626         *num_names = total_names;
627
628         return NT_STATUS_OK;
629 }
630
631 #ifdef HAVE_LDAP
632
633 #include <ldap.h>
634
635 static int get_ldap_seq(const char *server, int port, uint32 *seq)
636 {
637         int ret = -1;
638         struct timeval to;
639         const char *attrs[] = {"highestCommittedUSN", NULL};
640         LDAPMessage *res = NULL;
641         char **values = NULL;
642         LDAP *ldp = NULL;
643
644         *seq = DOM_SEQUENCE_NONE;
645
646         /*
647          * Parameterised (5) second timeout on open. This is needed as the
648          * search timeout doesn't seem to apply to doing an open as well. JRA.
649          */
650
651         ldp = ldap_open_with_timeout(server, port, lp_ldap_timeout());
652         if (ldp == NULL)
653                 return -1;
654
655         /* Timeout if no response within 20 seconds. */
656         to.tv_sec = 10;
657         to.tv_usec = 0;
658
659         if (ldap_search_st(ldp, "", LDAP_SCOPE_BASE, "(objectclass=*)",
660                            CONST_DISCARD(char **, attrs), 0, &to, &res))
661                 goto done;
662
663         if (ldap_count_entries(ldp, res) != 1)
664                 goto done;
665
666         values = ldap_get_values(ldp, res, "highestCommittedUSN");
667         if (!values || !values[0])
668                 goto done;
669
670         *seq = atoi(values[0]);
671         ret = 0;
672
673   done:
674
675         if (values)
676                 ldap_value_free(values);
677         if (res)
678                 ldap_msgfree(res);
679         if (ldp)
680                 ldap_unbind(ldp);
681         return ret;
682 }
683
684 /**********************************************************************
685  Get the sequence number for a Windows AD native mode domain using
686  LDAP queries
687 **********************************************************************/
688
689 static int get_ldap_sequence_number( const char* domain, uint32 *seq)
690 {
691         int ret = -1;
692         int i, port = LDAP_PORT;
693         struct ip_service *ip_list = NULL;
694         int count;
695         
696         if ( !get_sorted_dc_list(domain, &ip_list, &count, False) ) {
697                 DEBUG(3, ("Could not look up dc's for domain %s\n", domain));
698                 return False;
699         }
700
701         /* Finally return first DC that we can contact */
702
703         for (i = 0; i < count; i++) {
704                 fstring ipstr;
705
706                 /* since the is an LDAP lookup, default to the LDAP_PORT is
707                  * not set */
708                 port = (ip_list[i].port!= PORT_NONE) ?
709                         ip_list[i].port : LDAP_PORT;
710
711                 fstrcpy( ipstr, inet_ntoa(ip_list[i].ip) );
712                 
713                 if (is_zero_ip(ip_list[i].ip))
714                         continue;
715
716                 if ( (ret = get_ldap_seq( ipstr, port,  seq)) == 0 )
717                         goto done;
718
719                 /* add to failed connection cache */
720                 add_failed_connection_entry( domain, ipstr,
721                                              NT_STATUS_UNSUCCESSFUL );
722         }
723
724 done:
725         if ( ret == 0 ) {
726                 DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence "
727                           "number for Domain (%s) from DC (%s:%d)\n", 
728                         domain, inet_ntoa(ip_list[i].ip), port));
729         }
730
731         SAFE_FREE(ip_list);
732
733         return ret;
734 }
735
736 #endif /* HAVE_LDAP */
737
738 /* find the sequence number for a domain */
739 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
740 {
741         TALLOC_CTX *mem_ctx;
742         SAM_UNK_CTR ctr;
743         NTSTATUS result;
744         POLICY_HND dom_pol;
745         BOOL got_seq_num = False;
746         int retry;
747         struct rpc_pipe_client *cli;
748
749         DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name));
750
751         *seq = DOM_SEQUENCE_NONE;
752
753         if (!(mem_ctx = talloc_init("sequence_number[rpc]")))
754                 return NT_STATUS_NO_MEMORY;
755
756         retry = 0;
757
758 #ifdef HAVE_LDAP
759         if ( domain->native_mode ) 
760         {
761                 int res;
762
763                 DEBUG(8,("using get_ldap_seq() to retrieve the "
764                          "sequence number\n"));
765
766                 res =  get_ldap_sequence_number( domain->name, seq );
767                 if (res == 0)
768                 {                       
769                         result = NT_STATUS_OK;
770                         DEBUG(10,("domain_sequence_number: LDAP for "
771                                   "domain %s is %u\n",
772                                   domain->name, *seq));
773                         goto done;
774                 }
775
776                 DEBUG(10,("domain_sequence_number: failed to get LDAP "
777                           "sequence number for domain %s\n",
778                           domain->name ));
779         }
780 #endif /* HAVE_LDAP */
781
782         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
783         if (!NT_STATUS_IS_OK(result)) {
784                 goto done;
785         }
786
787         /* Query domain info */
788
789         result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 8, &ctr);
790
791         if (NT_STATUS_IS_OK(result)) {
792                 *seq = ctr.info.inf8.seq_num.low;
793                 got_seq_num = True;
794                 goto seq_num;
795         }
796
797         /* retry with info-level 2 in case the dc does not support info-level 8
798          * (like all older samba2 and samba3 dc's - Guenther */
799
800         result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 2, &ctr);
801         
802         if (NT_STATUS_IS_OK(result)) {
803                 *seq = ctr.info.inf2.seq_num.low;
804                 got_seq_num = True;
805         }
806
807  seq_num:
808         if (got_seq_num) {
809                 DEBUG(10,("domain_sequence_number: for domain %s is %u\n",
810                           domain->name, (unsigned)*seq));
811         } else {
812                 DEBUG(10,("domain_sequence_number: failed to get sequence "
813                           "number (%u) for domain %s\n",
814                           (unsigned)*seq, domain->name ));
815         }
816
817   done:
818
819         talloc_destroy(mem_ctx);
820
821         return result;
822 }
823
824 /* get a list of trusted domains */
825 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
826                                 TALLOC_CTX *mem_ctx,
827                                 uint32 *num_domains,
828                                 char ***names,
829                                 char ***alt_names,
830                                 DOM_SID **dom_sids)
831 {
832         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
833         uint32 enum_ctx = 0;
834         struct rpc_pipe_client *cli;
835         POLICY_HND lsa_policy;
836
837         DEBUG(3,("rpc: trusted_domains\n"));
838
839         *num_domains = 0;
840         *names = NULL;
841         *alt_names = NULL;
842         *dom_sids = NULL;
843
844         result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
845         if (!NT_STATUS_IS_OK(result))
846                 return result;
847
848         result = STATUS_MORE_ENTRIES;
849
850         while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
851                 uint32 start_idx, num;
852                 char **tmp_names;
853                 DOM_SID *tmp_sids;
854                 int i;
855
856                 result = rpccli_lsa_enum_trust_dom(cli, mem_ctx,
857                                                    &lsa_policy, &enum_ctx,
858                                                    &num, &tmp_names,
859                                                    &tmp_sids);
860
861                 if (!NT_STATUS_IS_OK(result) &&
862                     !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
863                         break;
864
865                 start_idx = *num_domains;
866                 *num_domains += num;
867                 *names = TALLOC_REALLOC_ARRAY(mem_ctx, *names,
868                                               char *, *num_domains);
869                 *dom_sids = TALLOC_REALLOC_ARRAY(mem_ctx, *dom_sids,
870                                                  DOM_SID, *num_domains);
871                 *alt_names = TALLOC_REALLOC_ARRAY(mem_ctx, *alt_names,
872                                                  char *, *num_domains);
873                 if ((*names == NULL) || (*dom_sids == NULL) ||
874                     (*alt_names == NULL))
875                         return NT_STATUS_NO_MEMORY;
876
877                 for (i=0; i<num; i++) {
878                         (*names)[start_idx+i] = tmp_names[i];
879                         (*dom_sids)[start_idx+i] = tmp_sids[i];
880                         (*alt_names)[start_idx+i] = talloc_strdup(mem_ctx, "");
881                 }
882         }
883         return result;
884 }
885
886 /* find alternate names list for the domain - none for rpc */
887 static NTSTATUS alternate_name(struct winbindd_domain *domain)
888 {
889         return NT_STATUS_OK;
890 }
891
892
893 /* the rpc backend methods are exposed via this structure */
894 struct winbindd_methods msrpc_methods = {
895         False,
896         query_user_list,
897         enum_dom_groups,
898         enum_local_groups,
899         msrpc_name_to_sid,
900         msrpc_sid_to_name,
901         query_user,
902         lookup_usergroups,
903         msrpc_lookup_useraliases,
904         lookup_groupmem,
905         sequence_number,
906         trusted_domains,
907         alternate_name
908 };