preparing for release of 2.2.3a
[Samba.git] / source / nsswitch / winbindd_util.c
blobc0c7b6ae0dd8b06f05c2b85ff5a18c8532319e4b
1 /*
2 Unix SMB/Netbios implementation.
4 Winbind daemon for ntdom nss module
6 Copyright (C) Tim Potter 2000-2001
7 Copyright (C) 2001 by Martin Pool <mbp@samba.org>
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "winbindd.h"
25 #include "sids.h"
27 /**
28 * @file winbindd_util.c
30 * Winbind daemon for NT domain authentication nss module.
31 **/
34 /**
35 * Used to clobber name fields that have an undefined value.
37 * Correct code should never look at a field that has this value.
38 **/
39 static const fstring name_deadbeef = "<deadbeef>";
42 /* Globals for domain list stuff */
44 struct winbindd_domain *domain_list = NULL;
46 /* Given a domain name, return the struct winbindd domain info for it
47 if it is actually working. */
49 struct winbindd_domain *find_domain_from_name(char *domain_name)
51 struct winbindd_domain *tmp;
53 if (domain_list == NULL)
54 get_domain_info();
56 /* Search through list */
58 for (tmp = domain_list; tmp != NULL; tmp = tmp->next) {
59 if (strcmp(domain_name, tmp->name) == 0)
60 return tmp;
63 /* Not found */
65 return NULL;
68 /* Given a domain name, return the struct winbindd domain info for it */
70 struct winbindd_domain *find_domain_from_sid(DOM_SID *sid)
72 struct winbindd_domain *tmp;
74 if (domain_list == NULL)
75 get_domain_info();
77 /* Search through list */
79 for (tmp = domain_list; tmp != NULL; tmp = tmp->next) {
80 if (sid_equal(sid, &tmp->sid))
81 return tmp;
84 /* Not found */
86 return NULL;
89 /* Add a trusted domain to our list of domains */
91 static struct winbindd_domain *add_trusted_domain(char *domain_name,
92 DOM_SID *domain_sid)
94 struct winbindd_domain *domain, *tmp;
96 for (tmp = domain_list; tmp != NULL; tmp = tmp->next) {
97 if (strcmp(domain_name, tmp->name) == 0) {
98 DEBUG(3, ("domain %s already in domain list\n", domain_name));
99 return tmp;
103 DEBUG(1, ("adding domain %s\n", domain_name));
105 /* Create new domain entry */
107 if ((domain = (struct winbindd_domain *)malloc(sizeof(*domain))) == NULL)
108 return NULL;
110 /* Fill in fields */
112 ZERO_STRUCTP(domain);
113 fstrcpy(domain->name, domain_name);
114 sid_copy(&domain->sid, domain_sid);
116 /* Link to domain list */
118 DLIST_ADD(domain_list, domain);
120 return domain;
123 /* Look up global info for the winbind daemon */
125 BOOL get_domain_info(void)
127 uint32 enum_ctx = 0, num_doms = 0;
128 char **domains = NULL;
129 DOM_SID *sids = NULL, domain_sid;
130 NTSTATUS result;
131 CLI_POLICY_HND *hnd;
132 int i;
133 fstring level5_dom;
134 BOOL rv = False;
135 TALLOC_CTX *mem_ctx;
137 DEBUG(1, ("getting trusted domain list\n"));
139 if (!(mem_ctx = talloc_init()))
140 return False;
142 /* Add our workgroup - keep handle to look up trusted domains */
144 if (!(hnd = cm_get_lsa_handle(lp_workgroup())))
145 goto done;
147 result = cli_lsa_query_info_policy(hnd->cli, mem_ctx,
148 &hnd->pol, 0x05, level5_dom, &domain_sid);
150 if (!NT_STATUS_IS_OK(result))
151 goto done;
153 add_trusted_domain(lp_workgroup(), &domain_sid);
155 /* Enumerate list of trusted domains */
157 if (!(hnd = cm_get_lsa_handle(lp_workgroup())))
158 goto done;
160 result = cli_lsa_enum_trust_dom(hnd->cli, mem_ctx,
161 &hnd->pol, &enum_ctx, &num_doms, &domains, &sids);
163 if (!NT_STATUS_IS_OK(result))
164 goto done;
166 /* Add each domain to the trusted domain list */
168 for(i = 0; i < num_doms; i++)
169 add_trusted_domain(domains[i], &sids[i]);
171 rv = True;
173 done:
175 talloc_destroy(mem_ctx);
177 return rv;
180 /* Free global domain info */
182 void free_domain_info(void)
184 struct winbindd_domain *domain;
186 /* Free list of domains */
188 if (domain_list) {
189 struct winbindd_domain *next_domain;
191 domain = domain_list;
193 while(domain) {
194 next_domain = domain->next;
195 SAFE_FREE(domain);
196 domain = next_domain;
201 /* Connect to a domain controller using get_any_dc_name() to discover
202 the domain name and sid */
204 BOOL lookup_domain_sid(char *domain_name, struct winbindd_domain *domain)
206 fstring level5_dom;
207 uint32 enum_ctx = 0, num_doms = 0;
208 char **domains = NULL;
209 DOM_SID *sids = NULL;
210 CLI_POLICY_HND *hnd;
211 NTSTATUS result;
212 BOOL rv = False;
213 TALLOC_CTX *mem_ctx;
215 DEBUG(1, ("looking up sid for domain %s\n", domain_name));
217 if (!(mem_ctx = talloc_init()))
218 return False;
220 if (!(hnd = cm_get_lsa_handle(domain_name)))
221 goto done;
223 /* Do a level 5 query info policy if we are looking up the SID for
224 our own domain. */
226 if (strequal(domain_name, lp_workgroup())) {
228 result = cli_lsa_query_info_policy(hnd->cli, mem_ctx,
229 &hnd->pol, 0x05, level5_dom,
230 &domain->sid);
232 rv = NT_STATUS_IS_OK(result);
233 goto done;
236 /* Use lsaenumdomains to get sid for this domain */
238 result = cli_lsa_enum_trust_dom(hnd->cli, mem_ctx, &hnd->pol,
239 &enum_ctx, &num_doms, &domains, &sids);
241 /* Look for domain name */
243 if (NT_STATUS_IS_OK(result) && domains && sids) {
244 BOOL found = False;
245 int i;
247 for(i = 0; i < num_doms; i++) {
248 if (strequal(domain_name, domains[i])) {
249 sid_copy(&domain->sid, &sids[i]);
250 found = True;
251 break;
255 rv = found;
256 goto done;
259 rv = False; /* An error occured with a trusted domain */
261 done:
263 talloc_destroy(mem_ctx);
265 return rv;
268 /* Store a SID in a domain indexed by name in the cache. */
270 static void store_sid_by_name_in_cache(fstring name, DOM_SID *sid, enum SID_NAME_USE type)
272 fstring domain_str;
273 char *p;
274 struct winbindd_sid sid_val;
275 struct winbindd_domain *domain;
277 /* Get name from domain. */
278 fstrcpy( domain_str, name);
279 p = strchr(domain_str, '\\');
280 if (p)
281 *p = '\0';
283 if ((domain = find_domain_from_name(domain_str)) == NULL)
284 return;
286 sid_to_string(sid_val.sid, sid);
287 sid_val.type = (int)type;
289 DEBUG(10,("store_sid_by_name_in_cache: storing cache entry %s -> SID %s\n",
290 name, sid_val.sid ));
292 winbindd_store_sid_cache_entry(domain, name, &sid_val);
295 /* Lookup a SID in a domain indexed by name in the cache. */
297 static BOOL winbindd_lookup_sid_by_name_in_cache(fstring name, DOM_SID *sid, enum SID_NAME_USE *type)
299 fstring domain_str;
300 char *p;
301 struct winbindd_sid sid_ret;
302 struct winbindd_domain *domain;
304 /* Get name from domain. */
305 fstrcpy( domain_str, name);
306 p = strchr(domain_str, '\\');
307 if (p)
308 *p = '\0';
310 if ((domain = find_domain_from_name(domain_str)) == NULL)
311 return False;
313 if (!winbindd_fetch_sid_cache_entry(domain, name, &sid_ret))
314 return False;
316 string_to_sid( sid, sid_ret.sid);
317 *type = (enum SID_NAME_USE)sid_ret.type;
319 DEBUG(10,("winbindd_lookup_sid_by_name_in_cache: Cache hit for name %s. SID = %s\n",
320 name, sid_ret.sid ));
322 return True;
325 /* Store a name in a domain indexed by SID in the cache. */
327 static void store_name_by_sid_in_cache(DOM_SID *sid, fstring name, enum SID_NAME_USE type)
329 fstring sid_str;
330 uint32 rid;
331 DOM_SID domain_sid;
332 struct winbindd_name name_val;
333 struct winbindd_domain *domain;
335 /* Split sid into domain sid and user rid */
336 sid_copy(&domain_sid, sid);
337 sid_split_rid(&domain_sid, &rid);
339 if ((domain = find_domain_from_sid(&domain_sid)) == NULL)
340 return;
342 sid_to_string(sid_str, sid);
343 fstrcpy( name_val.name, name );
344 name_val.type = (int)type;
346 DEBUG(10,("store_name_by_sid_in_cache: storing cache entry SID %s -> %s\n",
347 sid_str, name_val.name ));
349 winbindd_store_name_cache_entry(domain, sid_str, &name_val);
352 /* Lookup a name in a domain indexed by SID in the cache. */
354 static BOOL winbindd_lookup_name_by_sid_in_cache(DOM_SID *sid, fstring name, enum SID_NAME_USE *type)
356 fstring sid_str;
357 uint32 rid;
358 DOM_SID domain_sid;
359 struct winbindd_name name_ret;
360 struct winbindd_domain *domain;
362 /* Split sid into domain sid and user rid */
363 sid_copy(&domain_sid, sid);
364 sid_split_rid(&domain_sid, &rid);
366 if ((domain = find_domain_from_sid(&domain_sid)) == NULL)
367 return False;
369 sid_to_string(sid_str, sid);
371 if (!winbindd_fetch_name_cache_entry(domain, sid_str, &name_ret))
372 return False;
374 fstrcpy( name, name_ret.name );
375 *type = (enum SID_NAME_USE)name_ret.type;
377 DEBUG(10,("winbindd_lookup_name_by_sid_in_cache: Cache hit for SID = %s, name %s\n",
378 sid_str, name ));
380 return True;
383 /* Lookup a sid in a domain from a name */
385 BOOL winbindd_lookup_sid_by_name(char *name, DOM_SID *sid, enum SID_NAME_USE *type)
387 int num_sids = 0, num_names = 1;
388 DOM_SID *sids = NULL;
389 uint32 *types = NULL;
390 CLI_POLICY_HND *hnd;
391 NTSTATUS result;
392 TALLOC_CTX *mem_ctx;
393 BOOL rv = False;
395 /* Don't bother with machine accounts */
397 if (name[strlen(name) - 1] == '$')
398 return False;
400 /* First check cache. */
401 if (winbindd_lookup_sid_by_name_in_cache(name, sid, type)) {
402 if (*type == SID_NAME_USE_NONE)
403 return False; /* Negative cache hit. */
404 return True;
407 /* Lookup name */
409 if (!(mem_ctx = talloc_init()))
410 return False;
412 if (!(hnd = cm_get_lsa_handle(lp_workgroup())))
413 goto done;
415 result = cli_lsa_lookup_names(hnd->cli, mem_ctx, &hnd->pol,
416 num_names, (char **)&name, &sids,
417 &types, &num_sids);
419 /* Return rid and type if lookup successful */
421 if (NT_STATUS_IS_OK(result)) {
423 /* Return sid */
425 if ((sid != NULL) && (sids != NULL))
426 sid_copy(sid, &sids[0]);
428 /* Return name type */
430 if ((type != NULL) && (types != NULL))
431 *type = types[0];
433 /* Store the forward and reverse map of this lookup in the cache. */
434 store_sid_by_name_in_cache(name, &sids[0], types[0]);
435 store_name_by_sid_in_cache(&sids[0], name, types[0]);
436 } else {
437 /* JRA. Here's where we add the -ve cache store with a name type of SID_NAME_USE_NONE. */
438 DOM_SID nullsid;
440 ZERO_STRUCT(nullsid);
441 store_sid_by_name_in_cache(name, &nullsid, SID_NAME_USE_NONE);
442 *type = SID_NAME_UNKNOWN;
445 rv = NT_STATUS_IS_OK(result);
447 done:
448 talloc_destroy(mem_ctx);
450 return rv;
454 * @brief Lookup a name in a domain from a sid.
456 * @param sid Security ID you want to look up.
458 * @param name On success, set to the name corresponding to @p sid.
460 * @param type On success, contains the type of name: alias, group or
461 * user.
463 * @retval True if the name exists, in which case @p name and @p type
464 * are set, otherwise False.
466 BOOL winbindd_lookup_name_by_sid(DOM_SID *sid,
467 fstring name,
468 enum SID_NAME_USE *type)
470 int num_sids = 1, num_names = 0;
471 uint32 *types = NULL;
472 char **names;
473 CLI_POLICY_HND *hnd;
474 NTSTATUS result;
475 TALLOC_CTX *mem_ctx;
476 BOOL rv = False;
478 /* First check cache. */
479 if (winbindd_lookup_name_by_sid_in_cache(sid, name, type)) {
480 if (*type == SID_NAME_USE_NONE) {
481 fstrcpy(name, name_deadbeef);
482 *type = SID_NAME_UNKNOWN;
483 return False; /* Negative cache hit. */
484 } else
485 return True;
488 /* Lookup name */
490 if (!(mem_ctx = talloc_init()))
491 return False;
493 if (!(hnd = cm_get_lsa_handle(lp_workgroup())))
494 goto done;
496 result = cli_lsa_lookup_sids(hnd->cli, mem_ctx, &hnd->pol,
497 num_sids, sid, &names, &types,
498 &num_names);
500 /* Return name and type if successful */
502 if ((rv = NT_STATUS_IS_OK(result))) {
504 /* Return name */
506 if ((names != NULL) && (name != NULL))
507 fstrcpy(name, names[0]);
509 /* Return name type */
511 if ((type != NULL) && (types != NULL))
512 *type = types[0];
514 store_sid_by_name_in_cache(names[0], sid, types[0]);
515 store_name_by_sid_in_cache(sid, names[0], types[0]);
516 } else {
517 /* OK, so we tried to look up a name in this sid, and
518 * didn't find it. Therefore add a negative cache
519 * entry. */
520 store_name_by_sid_in_cache(sid, "", SID_NAME_USE_NONE);
521 *type = SID_NAME_UNKNOWN;
522 fstrcpy(name, name_deadbeef);
526 done:
527 talloc_destroy(mem_ctx);
529 return rv;
532 /* Lookup user information from a rid */
534 BOOL winbindd_lookup_userinfo(struct winbindd_domain *domain,
535 TALLOC_CTX *mem_ctx, uint32 user_rid,
536 SAM_USERINFO_CTR **user_info)
538 CLI_POLICY_HND *hnd;
539 uint16 info_level = 0x15;
540 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
541 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
542 POLICY_HND dom_pol, user_pol;
543 BOOL got_dom_pol = False, got_user_pol = False;
545 /* Get sam handle */
547 if (!(hnd = cm_get_sam_handle(domain->name)))
548 goto done;
550 /* Get domain handle */
552 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
553 des_access, &domain->sid, &dom_pol);
555 if (!NT_STATUS_IS_OK(result))
556 goto done;
558 got_dom_pol = True;
560 /* Get user handle */
562 result = cli_samr_open_user(hnd->cli, mem_ctx, &dom_pol,
563 des_access, user_rid, &user_pol);
565 if (!NT_STATUS_IS_OK(result))
566 goto done;
568 /* Get user info */
570 result = cli_samr_query_userinfo(hnd->cli, mem_ctx, &user_pol,
571 info_level, user_info);
573 cli_samr_close(hnd->cli, mem_ctx, &user_pol);
575 done:
576 /* Clean up policy handles */
578 if (got_user_pol)
579 cli_samr_close(hnd->cli, mem_ctx, &user_pol);
581 if (got_dom_pol)
582 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
584 return NT_STATUS_IS_OK(result);
587 /* Lookup groups a user is a member of. I wish Unix had a call like this! */
589 BOOL winbindd_lookup_usergroups(struct winbindd_domain *domain,
590 TALLOC_CTX *mem_ctx,
591 uint32 user_rid, uint32 *num_groups,
592 DOM_GID **user_groups)
594 CLI_POLICY_HND *hnd;
595 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
596 POLICY_HND dom_pol, user_pol;
597 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
598 BOOL got_dom_pol = False, got_user_pol = False;
600 /* Get sam handle */
602 if (!(hnd = cm_get_sam_handle(domain->name)))
603 goto done;
605 /* Get domain handle */
607 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
608 des_access, &domain->sid, &dom_pol);
610 if (!NT_STATUS_IS_OK(result))
611 goto done;
613 got_dom_pol = True;
615 /* Get user handle */
617 result = cli_samr_open_user(hnd->cli, mem_ctx, &dom_pol,
618 des_access, user_rid, &user_pol);
620 if (!NT_STATUS_IS_OK(result))
621 goto done;
623 got_user_pol = True;
625 /* Query user rids */
627 result = cli_samr_query_usergroups(hnd->cli, mem_ctx, &user_pol,
628 num_groups, user_groups);
630 done:
632 /* Clean up policy handles */
634 if (got_user_pol)
635 cli_samr_close(hnd->cli, mem_ctx, &user_pol);
637 if (got_dom_pol)
638 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
640 return NT_STATUS_IS_OK(result);
643 /* Lookup group membership given a rid. */
645 BOOL winbindd_lookup_groupmem(struct winbindd_domain *domain,
646 TALLOC_CTX *mem_ctx,
647 uint32 group_rid, uint32 *num_names,
648 uint32 **rid_mem, char ***names,
649 uint32 **name_types)
651 CLI_POLICY_HND *hnd;
652 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
653 uint32 i, total_names = 0;
654 POLICY_HND dom_pol, group_pol;
655 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
656 BOOL got_dom_pol = False, got_group_pol = False;
658 /* Get sam handle */
660 if (!(hnd = cm_get_sam_handle(domain->name)))
661 goto done;
663 /* Get domain handle */
665 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
666 des_access, &domain->sid, &dom_pol);
668 if (!NT_STATUS_IS_OK(result))
669 goto done;
671 got_dom_pol = True;
673 /* Get group handle */
675 result = cli_samr_open_group(hnd->cli, mem_ctx, &dom_pol,
676 des_access, group_rid, &group_pol);
678 if (!NT_STATUS_IS_OK(result))
679 goto done;
681 got_group_pol = True;
683 /* Step #1: Get a list of user rids that are the members of the
684 group. */
686 result = cli_samr_query_groupmem(hnd->cli, mem_ctx,
687 &group_pol, num_names, rid_mem,
688 name_types);
690 if (!NT_STATUS_IS_OK(result))
691 goto done;
693 /* Step #2: Convert list of rids into list of usernames. Do this
694 in bunches of ~1000 to avoid crashing NT4. It looks like there
695 is a buffer overflow or something like that lurking around
696 somewhere. */
698 #define MAX_LOOKUP_RIDS 900
700 *names = talloc(mem_ctx, *num_names * sizeof(char *));
701 *name_types = talloc(mem_ctx, *num_names * sizeof(uint32));
703 for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) {
704 int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS);
705 uint32 tmp_num_names = 0;
706 char **tmp_names = NULL;
707 uint32 *tmp_types = NULL;
709 /* Lookup a chunk of rids */
711 result = cli_samr_lookup_rids(hnd->cli, mem_ctx,
712 &dom_pol, 1000, /* flags */
713 num_lookup_rids,
714 &(*rid_mem)[i],
715 &tmp_num_names,
716 &tmp_names, &tmp_types);
718 if (!NT_STATUS_IS_OK(result))
719 goto done;
721 /* Copy result into array. The talloc system will take
722 care of freeing the temporary arrays later on. */
724 memcpy(&(*names)[i], tmp_names, sizeof(char *) *
725 tmp_num_names);
727 memcpy(&(*name_types)[i], tmp_types, sizeof(uint32) *
728 tmp_num_names);
730 total_names += tmp_num_names;
733 *num_names = total_names;
735 done:
736 if (got_group_pol)
737 cli_samr_close(hnd->cli, mem_ctx, &group_pol);
739 if (got_dom_pol)
740 cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
742 return NT_STATUS_IS_OK(result);
745 BOOL create_samr_domain_handle(struct winbindd_domain *domain, POLICY_HND *pdom_pol)
747 CLI_POLICY_HND *hnd;
748 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
749 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
750 TALLOC_CTX *mem_ctx = talloc_init();
752 ZERO_STRUCTP(pdom_pol);
754 if (!mem_ctx)
755 return False;
757 /* Get sam handle */
759 if (!(hnd = cm_get_sam_handle(domain->name))) {
760 talloc_destroy(mem_ctx);
761 return False;
763 /* Get domain handle */
764 result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
765 des_access, &domain->sid, pdom_pol);
767 talloc_destroy(mem_ctx);
768 if (!NT_STATUS_IS_OK(result))
769 return False;
771 return True;
774 void close_samr_domain_handle(struct winbindd_domain *domain, POLICY_HND *pdom_pol)
776 static POLICY_HND zero_pol;
777 CLI_POLICY_HND *hnd;
778 TALLOC_CTX *mem_ctx = talloc_init();
780 if (!mem_ctx)
781 return;
783 if (memcmp(pdom_pol, &zero_pol, sizeof(zero_pol)) == 0)
784 return;
786 if (!(hnd = cm_get_sam_handle(domain->name))) {
787 talloc_destroy(mem_ctx);
788 return;
791 cli_samr_close(hnd->cli, mem_ctx, pdom_pol);
792 ZERO_STRUCTP(pdom_pol);
794 talloc_destroy(mem_ctx);
797 /* Free state information held for {set,get,end}{pw,gr}ent() functions */
799 void free_getent_state(struct getent_state *state)
801 struct getent_state *temp;
803 /* Iterate over state list */
805 temp = state;
807 while(temp != NULL) {
808 struct getent_state *next;
810 /* Close SAMR cache handle. */
811 close_samr_domain_handle(temp->domain, &temp->dom_pol);
813 /* Free sam entries then list entry */
815 SAFE_FREE(state->sam_entries);
816 DLIST_REMOVE(state, state);
817 next = temp->next;
819 SAFE_FREE(temp);
820 temp = next;
824 struct getent_state *create_getent_state(struct winbindd_domain *domain)
826 struct getent_state *state = (struct getent_state *)malloc(sizeof(struct getent_state));
828 if (state == NULL)
829 return NULL;
831 ZERO_STRUCTP(state);
832 state->domain = domain;
834 /* Create and cache a SAMR domain handle. */
835 if (!create_samr_domain_handle(state->domain, &state->dom_pol)) {
836 free_getent_state(state);
837 return NULL;
840 return state;
843 /* Initialise trusted domain info */
845 BOOL winbindd_param_init(void)
847 /* Parse winbind uid and winbind_gid parameters */
849 if (!lp_winbind_uid(&server_state.uid_low, &server_state.uid_high)) {
850 DEBUG(0, ("winbind uid range missing or invalid\n"));
851 return False;
854 if (!lp_winbind_gid(&server_state.gid_low, &server_state.gid_high)) {
855 DEBUG(0, ("winbind gid range missing or invalid\n"));
856 return False;
859 return True;
862 /* Query display info for a domain. This returns enough information plus a
863 bit extra to give an overview of domain users for the User Manager
864 application. */
866 NTSTATUS winbindd_query_dispinfo(struct winbindd_domain *domain,
867 TALLOC_CTX *mem_ctx, POLICY_HND *pdom_pol,
868 uint32 *start_ndx, uint16 info_level,
869 uint32 *num_entries, SAM_DISPINFO_CTR *ctr)
871 CLI_POLICY_HND *hnd;
872 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
874 /* Get sam handle */
876 if (!(hnd = cm_get_sam_handle(domain->name)))
877 return NT_STATUS_UNSUCCESSFUL;
879 /* Query display info */
881 result = cli_samr_query_dispinfo(hnd->cli, mem_ctx,
882 pdom_pol, start_ndx, info_level,
883 num_entries, 0xffff, ctr);
885 return result;
888 /* Check if a domain is present in a comma-separated list of domains */
890 BOOL check_domain_env(char *domain_env, char *domain)
892 fstring name;
893 char *tmp = domain_env;
895 while(next_token(&tmp, name, ",", sizeof(fstring))) {
896 if (strequal(name, domain))
897 return True;
900 return False;
903 /* Parse a string of the form DOMAIN/user into a domain and a user */
905 BOOL parse_domain_user(char *domuser, fstring domain, fstring user)
907 char *p = strchr(domuser,*lp_winbind_separator());
909 if (!p)
910 return False;
912 fstrcpy(user, p+1);
913 fstrcpy(domain, domuser);
914 domain[PTR_DIFF(p, domuser)] = 0;
915 strupper(domain);
916 return True;