r20090: Fix a class of bugs found by James Peach. Ensure
[Samba/nascimento.git] / source3 / nsswitch / winbindd_rpc.c
blob08fe129db0e3f8b05e0ee38f9f5445ec7caa8894
1 /*
2 Unix SMB/CIFS implementation.
4 Winbind rpc backend functions
6 Copyright (C) Tim Potter 2000-2001,2003
7 Copyright (C) Andrew Tridgell 2001
8 Copyright (C) Volker Lendecke 2005
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.
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.
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.
25 #include "includes.h"
26 #include "winbindd.h"
28 #undef DBGC_CLASS
29 #define DBGC_CLASS DBGC_WINBIND
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)
40 NTSTATUS result;
41 POLICY_HND dom_pol;
42 unsigned int i, start_idx;
43 uint32 loop_count;
44 struct rpc_pipe_client *cli;
46 DEBUG(3,("rpc: query_user_list\n"));
48 *num_entries = 0;
49 *info = NULL;
51 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
52 if (!NT_STATUS_IS_OK(result))
53 return result;
55 i = start_idx = 0;
56 loop_count = 0;
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;
65 ZERO_STRUCT( ctr );
66 ZERO_STRUCT( info1 );
67 ctr.sam.info1 = &info1;
69 if (!(ctx2 = talloc_init("winbindd enum_users")))
70 return NT_STATUS_NO_MEMORY;
72 /* this next bit is copied from net_user_list_internal() */
74 get_query_dispinfo_params(loop_count, &max_entries,
75 &max_size);
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);
83 loop_count++;
85 *num_entries += num_dom_users;
87 *info = TALLOC_REALLOC_ARRAY(mem_ctx, *info, WINBIND_USERINFO,
88 *num_entries);
90 if (!(*info)) {
91 talloc_destroy(ctx2);
92 return NT_STATUS_NO_MEMORY;
95 for (j = 0; j < num_dom_users; i++, j++) {
96 fstring username, fullname;
97 uint32 rid = ctr.sam.info1->sam[j].rid_user;
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);
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);
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. */
116 sid_compose(&(*info)[i].group_sid, &domain->sid,
117 DOMAIN_GROUP_RID_USERS);
120 talloc_destroy(ctx2);
122 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
124 return result;
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)
133 POLICY_HND dom_pol;
134 NTSTATUS status;
135 uint32 start = 0;
136 struct rpc_pipe_client *cli;
138 *num_entries = 0;
139 *info = NULL;
141 DEBUG(3,("rpc: enum_dom_groups\n"));
143 status = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
144 if (!NT_STATUS_IS_OK(status))
145 return status;
147 do {
148 struct acct_info *info2 = NULL;
149 uint32 count = 0;
150 TALLOC_CTX *mem_ctx2;
152 mem_ctx2 = talloc_init("enum_dom_groups[rpc]");
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);
160 if (!NT_STATUS_IS_OK(status) &&
161 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
162 talloc_destroy(mem_ctx2);
163 break;
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;
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));
180 return NT_STATUS_OK;
183 /* List all domain groups */
185 static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
186 TALLOC_CTX *mem_ctx,
187 uint32 *num_entries,
188 struct acct_info **info)
190 POLICY_HND dom_pol;
191 NTSTATUS result;
192 struct rpc_pipe_client *cli;
194 *num_entries = 0;
195 *info = NULL;
197 DEBUG(3,("rpc: enum_local_groups\n"));
199 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
200 if (!NT_STATUS_IS_OK(result))
201 return result;
203 do {
204 struct acct_info *info2 = NULL;
205 uint32 count = 0, start = *num_entries;
206 TALLOC_CTX *mem_ctx2;
208 mem_ctx2 = talloc_init("enum_dom_local_groups[rpc]");
210 result = rpccli_samr_enum_als_groups( cli, mem_ctx2, &dom_pol,
211 &start, 0xFFFF, &info2,
212 &count);
214 if (!NT_STATUS_IS_OK(result) &&
215 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES) )
217 talloc_destroy(mem_ctx2);
218 return result;
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;
229 memcpy(&(*info)[*num_entries], info2, count*sizeof(*info2));
230 (*num_entries) += count;
231 talloc_destroy(mem_ctx2);
233 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
235 return NT_STATUS_OK;
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 lsa_SidType *type)
246 NTSTATUS result;
247 DOM_SID *sids = NULL;
248 enum lsa_SidType *types = NULL;
249 const char *full_name;
250 struct rpc_pipe_client *cli;
251 POLICY_HND lsa_policy;
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);
260 if (!full_name) {
261 DEBUG(0, ("talloc_asprintf failed!\n"));
262 return NT_STATUS_NO_MEMORY;
265 DEBUG(3,("name_to_sid [rpc] %s for domain %s\n", full_name?full_name:"", domain_name ));
267 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
268 if (!NT_STATUS_IS_OK(result))
269 return result;
271 result = rpccli_lsa_lookup_names(cli, mem_ctx, &lsa_policy, 1,
272 &full_name, NULL, &sids, &types);
274 if (!NT_STATUS_IS_OK(result))
275 return result;
277 /* Return rid and type if lookup successful */
279 sid_copy(sid, &sids[0]);
280 *type = types[0];
282 return NT_STATUS_OK;
286 convert a domain SID to a user or group name
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 lsa_SidType *type)
295 char **domains;
296 char **names;
297 enum lsa_SidType *types;
298 NTSTATUS result;
299 struct rpc_pipe_client *cli;
300 POLICY_HND lsa_policy;
302 DEBUG(3,("sid_to_name [rpc] %s for domain %s\n", sid_string_static(sid),
303 domain->name ));
305 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
306 if (!NT_STATUS_IS_OK(result))
307 return result;
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;
314 *type = (enum lsa_SidType)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;
321 NTSTATUS msrpc_rids_to_names(struct winbindd_domain *domain,
322 TALLOC_CTX *mem_ctx,
323 const DOM_SID *sid,
324 uint32 *rids,
325 size_t num_rids,
326 char **domain_name,
327 char ***names,
328 enum lsa_SidType **types)
330 char **domains;
331 NTSTATUS result;
332 struct rpc_pipe_client *cli;
333 POLICY_HND lsa_policy;
334 DOM_SID *sids;
335 size_t i;
337 DEBUG(3, ("rids_to_names [rpc] for domain %s\n", domain->name ));
339 sids = TALLOC_ARRAY(mem_ctx, DOM_SID, num_rids);
340 if (sids == NULL) {
341 return NT_STATUS_NO_MEMORY;
344 for (i=0; i<num_rids; i++) {
345 if (!sid_compose(&sids[i], sid, rids[i])) {
346 return NT_STATUS_INTERNAL_ERROR;
350 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
351 if (!NT_STATUS_IS_OK(result)) {
352 return result;
355 result = rpccli_lsa_lookup_sids(cli, mem_ctx, &lsa_policy,
356 num_rids, sids, &domains,
357 names, types);
358 if (!NT_STATUS_IS_OK(result) &&
359 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
360 return result;
363 for (i=0; i<num_rids; i++) {
364 if ((*types)[i] != SID_NAME_UNKNOWN) {
365 *domain_name = domains[i];
366 break;
370 return result;
373 /* Lookup user information from a rid or username. */
374 static NTSTATUS query_user(struct winbindd_domain *domain,
375 TALLOC_CTX *mem_ctx,
376 const DOM_SID *user_sid,
377 WINBIND_USERINFO *user_info)
379 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
380 POLICY_HND dom_pol, user_pol;
381 SAM_USERINFO_CTR *ctr;
382 fstring sid_string;
383 uint32 user_rid;
384 NET_USER_INFO_3 *user;
385 struct rpc_pipe_client *cli;
387 DEBUG(3,("rpc: query_user rid=%s\n",
388 sid_to_string(sid_string, user_sid)));
390 if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
391 return NT_STATUS_UNSUCCESSFUL;
393 /* try netsamlogon cache first */
395 if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL )
398 DEBUG(5,("query_user: Cache lookup succeeded for %s\n",
399 sid_string_static(user_sid)));
401 sid_compose(&user_info->user_sid, &domain->sid, user_rid);
402 sid_compose(&user_info->group_sid, &domain->sid,
403 user->group_rid);
405 user_info->acct_name = unistr2_tdup(mem_ctx,
406 &user->uni_user_name);
407 user_info->full_name = unistr2_tdup(mem_ctx,
408 &user->uni_full_name);
410 user_info->homedir = NULL;
411 user_info->shell = NULL;
413 SAFE_FREE(user);
415 return NT_STATUS_OK;
418 /* no cache; hit the wire */
420 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
421 if (!NT_STATUS_IS_OK(result))
422 return result;
424 /* Get user handle */
425 result = rpccli_samr_open_user(cli, mem_ctx, &dom_pol,
426 SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid,
427 &user_pol);
429 if (!NT_STATUS_IS_OK(result))
430 return result;
432 /* Get user info */
433 result = rpccli_samr_query_userinfo(cli, mem_ctx, &user_pol,
434 0x15, &ctr);
436 rpccli_samr_close(cli, mem_ctx, &user_pol);
438 if (!NT_STATUS_IS_OK(result))
439 return result;
441 sid_compose(&user_info->user_sid, &domain->sid, user_rid);
442 sid_compose(&user_info->group_sid, &domain->sid,
443 ctr->info.id21->group_rid);
444 user_info->acct_name = unistr2_tdup(mem_ctx,
445 &ctr->info.id21->uni_user_name);
446 user_info->full_name = unistr2_tdup(mem_ctx,
447 &ctr->info.id21->uni_full_name);
448 user_info->homedir = NULL;
449 user_info->shell = NULL;
451 return NT_STATUS_OK;
454 /* Lookup groups a user is a member of. I wish Unix had a call like this! */
455 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
456 TALLOC_CTX *mem_ctx,
457 const DOM_SID *user_sid,
458 uint32 *num_groups, DOM_SID **user_grpsids)
460 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
461 POLICY_HND dom_pol, user_pol;
462 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
463 DOM_GID *user_groups;
464 unsigned int i;
465 fstring sid_string;
466 uint32 user_rid;
467 struct rpc_pipe_client *cli;
469 DEBUG(3,("rpc: lookup_usergroups sid=%s\n",
470 sid_to_string(sid_string, user_sid)));
472 if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
473 return NT_STATUS_UNSUCCESSFUL;
475 *num_groups = 0;
476 *user_grpsids = NULL;
478 /* so lets see if we have a cached user_info_3 */
479 result = lookup_usergroups_cached(domain, mem_ctx, user_sid,
480 num_groups, user_grpsids);
482 if (NT_STATUS_IS_OK(result)) {
483 return NT_STATUS_OK;
486 /* no cache; hit the wire */
488 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
489 if (!NT_STATUS_IS_OK(result))
490 return result;
492 /* Get user handle */
493 result = rpccli_samr_open_user(cli, mem_ctx, &dom_pol,
494 des_access, user_rid, &user_pol);
496 if (!NT_STATUS_IS_OK(result))
497 return result;
499 /* Query user rids */
500 result = rpccli_samr_query_usergroups(cli, mem_ctx, &user_pol,
501 num_groups, &user_groups);
503 rpccli_samr_close(cli, mem_ctx, &user_pol);
505 if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0)
506 return result;
508 (*user_grpsids) = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_groups);
509 if (!(*user_grpsids))
510 return NT_STATUS_NO_MEMORY;
512 for (i=0;i<(*num_groups);i++) {
513 sid_copy(&((*user_grpsids)[i]), &domain->sid);
514 sid_append_rid(&((*user_grpsids)[i]),
515 user_groups[i].g_rid);
518 return NT_STATUS_OK;
521 NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain,
522 TALLOC_CTX *mem_ctx,
523 uint32 num_sids, const DOM_SID *sids,
524 uint32 *num_aliases, uint32 **alias_rids)
526 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
527 POLICY_HND dom_pol;
528 DOM_SID2 *query_sids;
529 uint32 num_query_sids = 0;
530 int i;
531 struct rpc_pipe_client *cli;
532 uint32 *alias_rids_query, num_aliases_query;
533 int rangesize = MAX_SAM_ENTRIES_W2K;
534 uint32 total_sids = 0;
535 int num_queries = 1;
537 *num_aliases = 0;
538 *alias_rids = NULL;
540 DEBUG(3,("rpc: lookup_useraliases\n"));
542 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
543 if (!NT_STATUS_IS_OK(result))
544 return result;
546 do {
547 /* prepare query */
549 num_query_sids = MIN(num_sids - total_sids, rangesize);
551 DEBUG(10,("rpc: lookup_useraliases: entering query %d for %d sids\n",
552 num_queries, num_query_sids));
555 query_sids = TALLOC_ARRAY(mem_ctx, DOM_SID2, num_query_sids);
556 if (query_sids == NULL) {
557 return NT_STATUS_NO_MEMORY;
560 for (i=0; i<num_query_sids; i++) {
561 sid_copy(&query_sids[i].sid, &sids[total_sids++]);
562 query_sids[i].num_auths = query_sids[i].sid.num_auths;
565 /* do request */
567 result = rpccli_samr_query_useraliases(cli, mem_ctx, &dom_pol,
568 num_query_sids, query_sids,
569 &num_aliases_query,
570 &alias_rids_query);
572 if (!NT_STATUS_IS_OK(result)) {
573 *num_aliases = 0;
574 *alias_rids = NULL;
575 TALLOC_FREE(query_sids);
576 goto done;
579 /* process output */
581 for (i=0; i<num_aliases_query; i++) {
582 size_t na = *num_aliases;
583 if (!add_rid_to_array_unique(mem_ctx, alias_rids_query[i],
584 alias_rids, &na)) {
585 return NT_STATUS_NO_MEMORY;
587 *num_aliases = na;
590 TALLOC_FREE(query_sids);
592 num_queries++;
594 } while (total_sids < num_sids);
596 done:
597 DEBUG(10,("rpc: lookup_useraliases: got %d aliases in %d queries "
598 "(rangesize: %d)\n", *num_aliases, num_queries, rangesize));
600 return result;
604 /* Lookup group membership given a rid. */
605 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
606 TALLOC_CTX *mem_ctx,
607 const DOM_SID *group_sid, uint32 *num_names,
608 DOM_SID **sid_mem, char ***names,
609 uint32 **name_types)
611 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
612 uint32 i, total_names = 0;
613 POLICY_HND dom_pol, group_pol;
614 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
615 uint32 *rid_mem = NULL;
616 uint32 group_rid;
617 unsigned int j;
618 fstring sid_string;
619 struct rpc_pipe_client *cli;
620 unsigned int orig_timeout;
622 DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain->name,
623 sid_to_string(sid_string, group_sid)));
625 if (!sid_peek_check_rid(&domain->sid, group_sid, &group_rid))
626 return NT_STATUS_UNSUCCESSFUL;
628 *num_names = 0;
630 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
631 if (!NT_STATUS_IS_OK(result))
632 return result;
634 result = rpccli_samr_open_group(cli, mem_ctx, &dom_pol,
635 des_access, group_rid, &group_pol);
637 if (!NT_STATUS_IS_OK(result))
638 return result;
640 /* Step #1: Get a list of user rids that are the members of the
641 group. */
643 /* This call can take a long time - allow the server to time out.
644 35 seconds should do it. */
646 orig_timeout = cli_set_timeout(cli->cli, 35000);
648 result = rpccli_samr_query_groupmem(cli, mem_ctx,
649 &group_pol, num_names, &rid_mem,
650 name_types);
652 /* And restore our original timeout. */
653 cli_set_timeout(cli->cli, orig_timeout);
655 rpccli_samr_close(cli, mem_ctx, &group_pol);
657 if (!NT_STATUS_IS_OK(result))
658 return result;
660 if (!*num_names) {
661 names = NULL;
662 name_types = NULL;
663 sid_mem = NULL;
664 return NT_STATUS_OK;
667 /* Step #2: Convert list of rids into list of usernames. Do this
668 in bunches of ~1000 to avoid crashing NT4. It looks like there
669 is a buffer overflow or something like that lurking around
670 somewhere. */
672 #define MAX_LOOKUP_RIDS 900
674 *names = TALLOC_ZERO_ARRAY(mem_ctx, char *, *num_names);
675 *name_types = TALLOC_ZERO_ARRAY(mem_ctx, uint32, *num_names);
676 *sid_mem = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, *num_names);
678 for (j=0;j<(*num_names);j++)
679 sid_compose(&(*sid_mem)[j], &domain->sid, rid_mem[j]);
681 if (*num_names>0 && (!*names || !*name_types))
682 return NT_STATUS_NO_MEMORY;
684 for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) {
685 int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS);
686 uint32 tmp_num_names = 0;
687 char **tmp_names = NULL;
688 uint32 *tmp_types = NULL;
690 /* Lookup a chunk of rids */
692 result = rpccli_samr_lookup_rids(cli, mem_ctx,
693 &dom_pol,
694 num_lookup_rids,
695 &rid_mem[i],
696 &tmp_num_names,
697 &tmp_names, &tmp_types);
699 /* see if we have a real error (and yes the
700 STATUS_SOME_UNMAPPED is the one returned from 2k) */
702 if (!NT_STATUS_IS_OK(result) &&
703 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
704 return result;
706 /* Copy result into array. The talloc system will take
707 care of freeing the temporary arrays later on. */
709 memcpy(&(*names)[i], tmp_names, sizeof(char *) *
710 tmp_num_names);
712 memcpy(&(*name_types)[i], tmp_types, sizeof(uint32) *
713 tmp_num_names);
715 total_names += tmp_num_names;
718 *num_names = total_names;
720 return NT_STATUS_OK;
723 #ifdef HAVE_LDAP
725 #include <ldap.h>
727 static int get_ldap_seq(const char *server, int port, uint32 *seq)
729 int ret = -1;
730 struct timeval to;
731 const char *attrs[] = {"highestCommittedUSN", NULL};
732 LDAPMessage *res = NULL;
733 char **values = NULL;
734 LDAP *ldp = NULL;
736 *seq = DOM_SEQUENCE_NONE;
739 * Parameterised (5) second timeout on open. This is needed as the
740 * search timeout doesn't seem to apply to doing an open as well. JRA.
743 ldp = ldap_open_with_timeout(server, port, lp_ldap_timeout());
744 if (ldp == NULL)
745 return -1;
747 /* Timeout if no response within 20 seconds. */
748 to.tv_sec = 10;
749 to.tv_usec = 0;
751 if (ldap_search_st(ldp, "", LDAP_SCOPE_BASE, "(objectclass=*)",
752 CONST_DISCARD(char **, attrs), 0, &to, &res))
753 goto done;
755 if (ldap_count_entries(ldp, res) != 1)
756 goto done;
758 values = ldap_get_values(ldp, res, "highestCommittedUSN");
759 if (!values || !values[0])
760 goto done;
762 *seq = atoi(values[0]);
763 ret = 0;
765 done:
767 if (values)
768 ldap_value_free(values);
769 if (res)
770 ldap_msgfree(res);
771 if (ldp)
772 ldap_unbind(ldp);
773 return ret;
776 /**********************************************************************
777 Get the sequence number for a Windows AD native mode domain using
778 LDAP queries.
779 **********************************************************************/
781 static int get_ldap_sequence_number(struct winbindd_domain *domain, uint32 *seq)
783 int ret = -1;
784 fstring ipstr;
786 fstrcpy( ipstr, inet_ntoa(domain->dcaddr.sin_addr));
787 if ((ret = get_ldap_seq( ipstr, LDAP_PORT, seq)) == 0) {
788 DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence "
789 "number for Domain (%s) from DC (%s)\n",
790 domain->name, ipstr));
792 return ret;
795 #endif /* HAVE_LDAP */
797 /* find the sequence number for a domain */
798 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
800 TALLOC_CTX *mem_ctx;
801 SAM_UNK_CTR ctr;
802 NTSTATUS result;
803 POLICY_HND dom_pol;
804 BOOL got_seq_num = False;
805 struct rpc_pipe_client *cli;
807 DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name));
809 *seq = DOM_SEQUENCE_NONE;
811 if (!(mem_ctx = talloc_init("sequence_number[rpc]")))
812 return NT_STATUS_NO_MEMORY;
814 #ifdef HAVE_LDAP
815 if ( domain->native_mode )
817 int res;
819 DEBUG(8,("using get_ldap_seq() to retrieve the "
820 "sequence number\n"));
822 res = get_ldap_sequence_number( domain, seq );
823 if (res == 0)
825 result = NT_STATUS_OK;
826 DEBUG(10,("domain_sequence_number: LDAP for "
827 "domain %s is %u\n",
828 domain->name, *seq));
829 goto done;
832 DEBUG(10,("domain_sequence_number: failed to get LDAP "
833 "sequence number for domain %s\n",
834 domain->name ));
836 #endif /* HAVE_LDAP */
838 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
839 if (!NT_STATUS_IS_OK(result)) {
840 goto done;
843 /* Query domain info */
845 result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 8, &ctr);
847 if (NT_STATUS_IS_OK(result)) {
848 *seq = ctr.info.inf8.seq_num;
849 got_seq_num = True;
850 goto seq_num;
853 /* retry with info-level 2 in case the dc does not support info-level 8
854 * (like all older samba2 and samba3 dc's - Guenther */
856 result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 2, &ctr);
858 if (NT_STATUS_IS_OK(result)) {
859 *seq = ctr.info.inf2.seq_num;
860 got_seq_num = True;
863 seq_num:
864 if (got_seq_num) {
865 DEBUG(10,("domain_sequence_number: for domain %s is %u\n",
866 domain->name, (unsigned)*seq));
867 } else {
868 DEBUG(10,("domain_sequence_number: failed to get sequence "
869 "number (%u) for domain %s\n",
870 (unsigned)*seq, domain->name ));
873 done:
875 talloc_destroy(mem_ctx);
877 return result;
880 /* get a list of trusted domains */
881 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
882 TALLOC_CTX *mem_ctx,
883 uint32 *num_domains,
884 char ***names,
885 char ***alt_names,
886 DOM_SID **dom_sids)
888 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
889 uint32 enum_ctx = 0;
890 struct rpc_pipe_client *cli;
891 POLICY_HND lsa_policy;
893 DEBUG(3,("rpc: trusted_domains\n"));
895 *num_domains = 0;
896 *names = NULL;
897 *alt_names = NULL;
898 *dom_sids = NULL;
900 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
901 if (!NT_STATUS_IS_OK(result))
902 return result;
904 result = STATUS_MORE_ENTRIES;
906 while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
907 uint32 start_idx, num;
908 char **tmp_names;
909 DOM_SID *tmp_sids;
910 int i;
912 result = rpccli_lsa_enum_trust_dom(cli, mem_ctx,
913 &lsa_policy, &enum_ctx,
914 &num, &tmp_names,
915 &tmp_sids);
917 if (!NT_STATUS_IS_OK(result) &&
918 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
919 break;
921 start_idx = *num_domains;
922 *num_domains += num;
923 *names = TALLOC_REALLOC_ARRAY(mem_ctx, *names,
924 char *, *num_domains);
925 *dom_sids = TALLOC_REALLOC_ARRAY(mem_ctx, *dom_sids,
926 DOM_SID, *num_domains);
927 *alt_names = TALLOC_REALLOC_ARRAY(mem_ctx, *alt_names,
928 char *, *num_domains);
929 if ((*names == NULL) || (*dom_sids == NULL) ||
930 (*alt_names == NULL))
931 return NT_STATUS_NO_MEMORY;
933 for (i=0; i<num; i++) {
934 (*names)[start_idx+i] = tmp_names[i];
935 (*dom_sids)[start_idx+i] = tmp_sids[i];
936 (*alt_names)[start_idx+i] = talloc_strdup(mem_ctx, "");
939 return result;
942 /* find the lockout policy for a domain */
943 NTSTATUS msrpc_lockout_policy(struct winbindd_domain *domain,
944 TALLOC_CTX *mem_ctx,
945 SAM_UNK_INFO_12 *lockout_policy)
947 NTSTATUS result;
948 struct rpc_pipe_client *cli;
949 POLICY_HND dom_pol;
950 SAM_UNK_CTR ctr;
952 DEBUG(10,("rpc: fetch lockout policy for %s\n", domain->name));
954 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
955 if (!NT_STATUS_IS_OK(result)) {
956 goto done;
959 result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 12, &ctr);
960 if (!NT_STATUS_IS_OK(result)) {
961 goto done;
964 *lockout_policy = ctr.info.inf12;
966 DEBUG(10,("msrpc_lockout_policy: bad_attempt_lockout %d\n",
967 ctr.info.inf12.bad_attempt_lockout));
969 done:
971 return result;
974 /* find the password policy for a domain */
975 NTSTATUS msrpc_password_policy(struct winbindd_domain *domain,
976 TALLOC_CTX *mem_ctx,
977 SAM_UNK_INFO_1 *password_policy)
979 NTSTATUS result;
980 struct rpc_pipe_client *cli;
981 POLICY_HND dom_pol;
982 SAM_UNK_CTR ctr;
984 DEBUG(10,("rpc: fetch password policy for %s\n", domain->name));
986 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
987 if (!NT_STATUS_IS_OK(result)) {
988 goto done;
991 result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 1, &ctr);
992 if (!NT_STATUS_IS_OK(result)) {
993 goto done;
996 *password_policy = ctr.info.inf1;
998 DEBUG(10,("msrpc_password_policy: min_length_password %d\n",
999 ctr.info.inf1.min_length_password));
1001 done:
1003 return result;
1007 /* the rpc backend methods are exposed via this structure */
1008 struct winbindd_methods msrpc_methods = {
1009 False,
1010 query_user_list,
1011 enum_dom_groups,
1012 enum_local_groups,
1013 msrpc_name_to_sid,
1014 msrpc_sid_to_name,
1015 msrpc_rids_to_names,
1016 query_user,
1017 lookup_usergroups,
1018 msrpc_lookup_useraliases,
1019 lookup_groupmem,
1020 sequence_number,
1021 msrpc_lockout_policy,
1022 msrpc_password_policy,
1023 trusted_domains,