r20124: clean up nested extern declaration warnings
[Samba.git] / source3 / nsswitch / winbindd_util.c
blobe4b51019aa79e84f98433a7a01c200b40f49880f
1 /*
2 Unix SMB/CIFS 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 "includes.h"
25 #include "winbindd.h"
27 #undef DBGC_CLASS
28 #define DBGC_CLASS DBGC_WINBIND
30 extern struct winbindd_methods cache_methods;
31 extern struct winbindd_methods passdb_methods;
33 /**
34 * @file winbindd_util.c
36 * Winbind daemon for NT domain authentication nss module.
37 **/
40 /**
41 * Used to clobber name fields that have an undefined value.
43 * Correct code should never look at a field that has this value.
44 **/
46 static const fstring name_deadbeef = "<deadbeef>";
48 /* The list of trusted domains. Note that the list can be deleted and
49 recreated using the init_domain_list() function so pointers to
50 individual winbindd_domain structures cannot be made. Keep a copy of
51 the domain name instead. */
53 static struct winbindd_domain *_domain_list;
55 /**
56 When was the last scan of trusted domains done?
58 0 == not ever
61 static time_t last_trustdom_scan;
63 struct winbindd_domain *domain_list(void)
65 /* Initialise list */
67 if ((!_domain_list) && (!init_domain_list())) {
68 smb_panic("Init_domain_list failed\n");
71 return _domain_list;
74 /* Free all entries in the trusted domain list */
76 void free_domain_list(void)
78 struct winbindd_domain *domain = _domain_list;
80 while(domain) {
81 struct winbindd_domain *next = domain->next;
83 DLIST_REMOVE(_domain_list, domain);
84 SAFE_FREE(domain);
85 domain = next;
89 static BOOL is_internal_domain(const DOM_SID *sid)
91 if (sid == NULL)
92 return False;
94 return (sid_check_is_domain(sid) || sid_check_is_builtin(sid));
97 static BOOL is_in_internal_domain(const DOM_SID *sid)
99 if (sid == NULL)
100 return False;
102 return (sid_check_is_in_our_domain(sid) || sid_check_is_in_builtin(sid));
106 /* Add a trusted domain to our list of domains */
107 static struct winbindd_domain *add_trusted_domain(const char *domain_name, const char *alt_name,
108 struct winbindd_methods *methods,
109 const DOM_SID *sid)
111 struct winbindd_domain *domain;
112 const char *alternative_name = NULL;
114 /* ignore alt_name if we are not in an AD domain */
116 if ( (lp_security() == SEC_ADS) && alt_name && *alt_name) {
117 alternative_name = alt_name;
120 /* We can't call domain_list() as this function is called from
121 init_domain_list() and we'll get stuck in a loop. */
122 for (domain = _domain_list; domain; domain = domain->next) {
123 if (strequal(domain_name, domain->name) ||
124 strequal(domain_name, domain->alt_name)) {
125 return domain;
127 if (alternative_name && *alternative_name) {
128 if (strequal(alternative_name, domain->name) ||
129 strequal(alternative_name, domain->alt_name)) {
130 return domain;
133 if (sid) {
134 if (is_null_sid(sid)) {
136 } else if (sid_equal(sid, &domain->sid)) {
137 return domain;
142 /* Create new domain entry */
144 if ((domain = SMB_MALLOC_P(struct winbindd_domain)) == NULL)
145 return NULL;
147 /* Fill in fields */
149 ZERO_STRUCTP(domain);
151 /* prioritise the short name */
152 if (strchr_m(domain_name, '.') && alternative_name && *alternative_name) {
153 fstrcpy(domain->name, alternative_name);
154 fstrcpy(domain->alt_name, domain_name);
155 } else {
156 fstrcpy(domain->name, domain_name);
157 if (alternative_name) {
158 fstrcpy(domain->alt_name, alternative_name);
162 domain->methods = methods;
163 domain->backend = NULL;
164 domain->internal = is_internal_domain(sid);
165 domain->sequence_number = DOM_SEQUENCE_NONE;
166 domain->last_seq_check = 0;
167 domain->initialized = False;
168 domain->online = is_internal_domain(sid);
169 domain->check_online_timeout = 0;
170 if (sid) {
171 sid_copy(&domain->sid, sid);
174 /* Link to domain list */
175 DLIST_ADD(_domain_list, domain);
177 DEBUG(2,("Added domain %s %s %s\n",
178 domain->name, domain->alt_name,
179 &domain->sid?sid_string_static(&domain->sid):""));
181 return domain;
184 /********************************************************************
185 rescan our domains looking for new trusted domains
186 ********************************************************************/
188 struct trustdom_state {
189 TALLOC_CTX *mem_ctx;
190 struct winbindd_response *response;
193 static void trustdom_recv(void *private_data, BOOL success);
195 static void add_trusted_domains( struct winbindd_domain *domain )
197 TALLOC_CTX *mem_ctx;
198 struct winbindd_request *request;
199 struct winbindd_response *response;
201 struct trustdom_state *state;
203 mem_ctx = talloc_init("add_trusted_domains");
204 if (mem_ctx == NULL) {
205 DEBUG(0, ("talloc_init failed\n"));
206 return;
209 request = TALLOC_ZERO_P(mem_ctx, struct winbindd_request);
210 response = TALLOC_P(mem_ctx, struct winbindd_response);
211 state = TALLOC_P(mem_ctx, struct trustdom_state);
213 if ((request == NULL) || (response == NULL) || (state == NULL)) {
214 DEBUG(0, ("talloc failed\n"));
215 talloc_destroy(mem_ctx);
216 return;
219 state->mem_ctx = mem_ctx;
220 state->response = response;
222 request->length = sizeof(*request);
223 request->cmd = WINBINDD_LIST_TRUSTDOM;
225 async_domain_request(mem_ctx, domain, request, response,
226 trustdom_recv, state);
229 static void trustdom_recv(void *private_data, BOOL success)
231 struct trustdom_state *state =
232 talloc_get_type_abort(private_data, struct trustdom_state);
233 struct winbindd_response *response = state->response;
234 char *p;
236 if ((!success) || (response->result != WINBINDD_OK)) {
237 DEBUG(1, ("Could not receive trustdoms\n"));
238 talloc_destroy(state->mem_ctx);
239 return;
242 p = (char *)response->extra_data.data;
244 while ((p != NULL) && (*p != '\0')) {
245 char *q, *sidstr, *alt_name;
246 DOM_SID sid;
248 alt_name = strchr(p, '\\');
249 if (alt_name == NULL) {
250 DEBUG(0, ("Got invalid trustdom response\n"));
251 break;
254 *alt_name = '\0';
255 alt_name += 1;
257 sidstr = strchr(alt_name, '\\');
258 if (sidstr == NULL) {
259 DEBUG(0, ("Got invalid trustdom response\n"));
260 break;
263 *sidstr = '\0';
264 sidstr += 1;
266 q = strchr(sidstr, '\n');
267 if (q != NULL)
268 *q = '\0';
270 if (!string_to_sid(&sid, sidstr)) {
271 DEBUG(0, ("Got invalid trustdom response\n"));
272 break;
275 if (find_domain_from_name_noinit(p) == NULL) {
276 struct winbindd_domain *domain;
277 char *alternate_name = NULL;
279 /* use the real alt_name if we have one, else pass in NULL */
281 if ( !strequal( alt_name, "(null)" ) )
282 alternate_name = alt_name;
284 domain = add_trusted_domain(p, alternate_name,
285 &cache_methods,
286 &sid);
287 setup_domain_child(domain, &domain->child, NULL);
289 p=q;
290 if (p != NULL)
291 p += 1;
294 SAFE_FREE(response->extra_data.data);
295 talloc_destroy(state->mem_ctx);
298 /********************************************************************
299 Periodically we need to refresh the trusted domain cache for smbd
300 ********************************************************************/
302 void rescan_trusted_domains( void )
304 time_t now = time(NULL);
306 /* see if the time has come... */
308 if ((now >= last_trustdom_scan) &&
309 ((now-last_trustdom_scan) < WINBINDD_RESCAN_FREQ) )
310 return;
312 /* this will only add new domains we didn't already know about */
314 add_trusted_domains( find_our_domain() );
316 last_trustdom_scan = now;
318 return;
321 struct init_child_state {
322 TALLOC_CTX *mem_ctx;
323 struct winbindd_domain *domain;
324 struct winbindd_request *request;
325 struct winbindd_response *response;
326 void (*continuation)(void *private_data, BOOL success);
327 void *private_data;
330 static void init_child_recv(void *private_data, BOOL success);
331 static void init_child_getdc_recv(void *private_data, BOOL success);
333 enum winbindd_result init_child_connection(struct winbindd_domain *domain,
334 void (*continuation)(void *private_data,
335 BOOL success),
336 void *private_data)
338 TALLOC_CTX *mem_ctx;
339 struct winbindd_request *request;
340 struct winbindd_response *response;
341 struct init_child_state *state;
342 struct winbindd_domain *request_domain;
344 mem_ctx = talloc_init("init_child_connection");
345 if (mem_ctx == NULL) {
346 DEBUG(0, ("talloc_init failed\n"));
347 return WINBINDD_ERROR;
350 request = TALLOC_ZERO_P(mem_ctx, struct winbindd_request);
351 response = TALLOC_P(mem_ctx, struct winbindd_response);
352 state = TALLOC_P(mem_ctx, struct init_child_state);
354 if ((request == NULL) || (response == NULL) || (state == NULL)) {
355 DEBUG(0, ("talloc failed\n"));
356 TALLOC_FREE(mem_ctx);
357 continuation(private_data, False);
358 return WINBINDD_ERROR;
361 request->length = sizeof(*request);
363 state->mem_ctx = mem_ctx;
364 state->domain = domain;
365 state->request = request;
366 state->response = response;
367 state->continuation = continuation;
368 state->private_data = private_data;
370 if (IS_DC || domain->primary) {
371 /* The primary domain has to find the DC name itself */
372 request->cmd = WINBINDD_INIT_CONNECTION;
373 fstrcpy(request->domain_name, domain->name);
374 request->data.init_conn.is_primary = True;
375 fstrcpy(request->data.init_conn.dcname, "");
376 async_request(mem_ctx, &domain->child, request, response,
377 init_child_recv, state);
378 return WINBINDD_PENDING;
381 /* This is *not* the primary domain, let's ask our DC about a DC
382 * name */
384 request->cmd = WINBINDD_GETDCNAME;
385 fstrcpy(request->domain_name, domain->name);
387 /* save online flag */
388 request_domain = find_our_domain();
389 request_domain->online = domain->online;
391 async_domain_request(mem_ctx, request_domain, request, response,
392 init_child_getdc_recv, state);
393 return WINBINDD_PENDING;
396 static void init_child_getdc_recv(void *private_data, BOOL success)
398 struct init_child_state *state =
399 talloc_get_type_abort(private_data, struct init_child_state);
400 const char *dcname = "";
402 DEBUG(10, ("Received getdcname response\n"));
404 if (success && (state->response->result == WINBINDD_OK)) {
405 dcname = state->response->data.dc_name;
408 state->request->cmd = WINBINDD_INIT_CONNECTION;
409 fstrcpy(state->request->domain_name, state->domain->name);
410 state->request->data.init_conn.is_primary = False;
411 fstrcpy(state->request->data.init_conn.dcname, dcname);
413 async_request(state->mem_ctx, &state->domain->child,
414 state->request, state->response,
415 init_child_recv, state);
418 static void init_child_recv(void *private_data, BOOL success)
420 struct init_child_state *state =
421 talloc_get_type_abort(private_data, struct init_child_state);
423 DEBUG(5, ("Received child initialization response for domain %s\n",
424 state->domain->name));
426 if ((!success) || (state->response->result != WINBINDD_OK)) {
427 DEBUG(3, ("Could not init child\n"));
428 state->continuation(state->private_data, False);
429 talloc_destroy(state->mem_ctx);
430 return;
433 fstrcpy(state->domain->name,
434 state->response->data.domain_info.name);
435 fstrcpy(state->domain->alt_name,
436 state->response->data.domain_info.alt_name);
437 string_to_sid(&state->domain->sid,
438 state->response->data.domain_info.sid);
439 state->domain->native_mode =
440 state->response->data.domain_info.native_mode;
441 state->domain->active_directory =
442 state->response->data.domain_info.active_directory;
443 state->domain->sequence_number =
444 state->response->data.domain_info.sequence_number;
446 state->domain->initialized = 1;
448 if (state->continuation != NULL)
449 state->continuation(state->private_data, True);
450 talloc_destroy(state->mem_ctx);
453 enum winbindd_result winbindd_dual_init_connection(struct winbindd_domain *domain,
454 struct winbindd_cli_state *state)
456 /* Ensure null termination */
457 state->request.domain_name
458 [sizeof(state->request.domain_name)-1]='\0';
459 state->request.data.init_conn.dcname
460 [sizeof(state->request.data.init_conn.dcname)-1]='\0';
462 if (strlen(state->request.data.init_conn.dcname) > 0) {
463 fstrcpy(domain->dcname, state->request.data.init_conn.dcname);
466 init_dc_connection(domain);
468 if (!domain->initialized) {
469 /* If we return error here we can't do any cached authentication,
470 but we may be in disconnected mode and can't initialize correctly.
471 Do what the previous code did and just return without initialization,
472 once we go online we'll re-initialize.
474 DEBUG(5, ("winbindd_dual_init_connection: %s returning without initialization "
475 "online = %d\n", domain->name, (int)domain->online ));
478 fstrcpy(state->response.data.domain_info.name, domain->name);
479 fstrcpy(state->response.data.domain_info.alt_name, domain->alt_name);
480 fstrcpy(state->response.data.domain_info.sid,
481 sid_string_static(&domain->sid));
483 state->response.data.domain_info.native_mode
484 = domain->native_mode;
485 state->response.data.domain_info.active_directory
486 = domain->active_directory;
487 state->response.data.domain_info.primary
488 = domain->primary;
489 state->response.data.domain_info.sequence_number =
490 domain->sequence_number;
492 return WINBINDD_OK;
495 /* Look up global info for the winbind daemon */
496 BOOL init_domain_list(void)
498 struct winbindd_domain *domain;
499 int role = lp_server_role();
501 /* Free existing list */
502 free_domain_list();
504 /* Add ourselves as the first entry. */
506 if ( role == ROLE_DOMAIN_MEMBER ) {
507 DOM_SID our_sid;
509 if (!secrets_fetch_domain_sid(lp_workgroup(), &our_sid)) {
510 DEBUG(0, ("Could not fetch our SID - did we join?\n"));
511 return False;
514 domain = add_trusted_domain( lp_workgroup(), lp_realm(),
515 &cache_methods, &our_sid);
516 domain->primary = True;
517 setup_domain_child(domain, &domain->child, NULL);
520 /* Local SAM */
522 domain = add_trusted_domain(get_global_sam_name(), NULL,
523 &passdb_methods, get_global_sam_sid());
524 if ( role != ROLE_DOMAIN_MEMBER ) {
525 domain->primary = True;
527 setup_domain_child(domain, &domain->child, NULL);
529 /* BUILTIN domain */
531 domain = add_trusted_domain("BUILTIN", NULL, &passdb_methods,
532 &global_sid_Builtin);
533 setup_domain_child(domain, &domain->child, NULL);
535 return True;
538 /**
539 * Given a domain name, return the struct winbindd domain info for it
541 * @note Do *not* pass lp_workgroup() to this function. domain_list
542 * may modify it's value, and free that pointer. Instead, our local
543 * domain may be found by calling find_our_domain().
544 * directly.
547 * @return The domain structure for the named domain, if it is working.
550 struct winbindd_domain *find_domain_from_name_noinit(const char *domain_name)
552 struct winbindd_domain *domain;
554 /* Search through list */
556 for (domain = domain_list(); domain != NULL; domain = domain->next) {
557 if (strequal(domain_name, domain->name) ||
558 (domain->alt_name[0] &&
559 strequal(domain_name, domain->alt_name))) {
560 return domain;
564 /* Not found */
566 return NULL;
569 struct winbindd_domain *find_domain_from_name(const char *domain_name)
571 struct winbindd_domain *domain;
573 domain = find_domain_from_name_noinit(domain_name);
575 if (domain == NULL)
576 return NULL;
578 if (!domain->initialized)
579 init_dc_connection(domain);
581 return domain;
584 /* Given a domain sid, return the struct winbindd domain info for it */
586 struct winbindd_domain *find_domain_from_sid_noinit(const DOM_SID *sid)
588 struct winbindd_domain *domain;
590 /* Search through list */
592 for (domain = domain_list(); domain != NULL; domain = domain->next) {
593 if (sid_compare_domain(sid, &domain->sid) == 0)
594 return domain;
597 /* Not found */
599 return NULL;
602 /* Given a domain sid, return the struct winbindd domain info for it */
604 struct winbindd_domain *find_domain_from_sid(const DOM_SID *sid)
606 struct winbindd_domain *domain;
608 domain = find_domain_from_sid_noinit(sid);
610 if (domain == NULL)
611 return NULL;
613 if (!domain->initialized)
614 init_dc_connection(domain);
616 return domain;
619 struct winbindd_domain *find_our_domain(void)
621 struct winbindd_domain *domain;
623 /* Search through list */
625 for (domain = domain_list(); domain != NULL; domain = domain->next) {
626 if (domain->primary)
627 return domain;
630 smb_panic("Could not find our domain\n");
631 return NULL;
634 struct winbindd_domain *find_builtin_domain(void)
636 DOM_SID sid;
637 struct winbindd_domain *domain;
639 string_to_sid(&sid, "S-1-5-32");
640 domain = find_domain_from_sid(&sid);
642 if (domain == NULL)
643 smb_panic("Could not find BUILTIN domain\n");
645 return domain;
648 /* Find the appropriate domain to lookup a name or SID */
650 struct winbindd_domain *find_lookup_domain_from_sid(const DOM_SID *sid)
652 /* A DC can't ask the local smbd for remote SIDs, here winbindd is the
653 * one to contact the external DC's. On member servers the internal
654 * domains are different: These are part of the local SAM. */
656 DEBUG(10, ("find_lookup_domain_from_sid(%s)\n",
657 sid_string_static(sid)));
659 if (IS_DC || is_internal_domain(sid) || is_in_internal_domain(sid)) {
660 DEBUG(10, ("calling find_domain_from_sid\n"));
661 return find_domain_from_sid(sid);
664 /* On a member server a query for SID or name can always go to our
665 * primary DC. */
667 DEBUG(10, ("calling find_our_domain\n"));
668 return find_our_domain();
671 struct winbindd_domain *find_lookup_domain_from_name(const char *domain_name)
673 if (IS_DC || strequal(domain_name, "BUILTIN") ||
674 strequal(domain_name, get_global_sam_name()))
675 return find_domain_from_name_noinit(domain_name);
677 return find_our_domain();
680 /* Lookup a sid in a domain from a name */
682 BOOL winbindd_lookup_sid_by_name(TALLOC_CTX *mem_ctx,
683 struct winbindd_domain *domain,
684 const char *domain_name,
685 const char *name, DOM_SID *sid,
686 enum lsa_SidType *type)
688 NTSTATUS result;
690 /* Lookup name */
691 result = domain->methods->name_to_sid(domain, mem_ctx, domain_name, name, sid, type);
693 /* Return rid and type if lookup successful */
694 if (!NT_STATUS_IS_OK(result)) {
695 *type = SID_NAME_UNKNOWN;
698 return NT_STATUS_IS_OK(result);
702 * @brief Lookup a name in a domain from a sid.
704 * @param sid Security ID you want to look up.
705 * @param name On success, set to the name corresponding to @p sid.
706 * @param dom_name On success, set to the 'domain name' corresponding to @p sid.
707 * @param type On success, contains the type of name: alias, group or
708 * user.
709 * @retval True if the name exists, in which case @p name and @p type
710 * are set, otherwise False.
712 BOOL winbindd_lookup_name_by_sid(TALLOC_CTX *mem_ctx,
713 DOM_SID *sid,
714 char **dom_name,
715 char **name,
716 enum lsa_SidType *type)
718 NTSTATUS result;
719 struct winbindd_domain *domain;
721 domain = find_lookup_domain_from_sid(sid);
723 if (!domain) {
724 DEBUG(1,("Can't find domain from sid\n"));
725 return False;
728 /* Lookup name */
730 result = domain->methods->sid_to_name(domain, mem_ctx, sid, dom_name, name, type);
732 /* Return name and type if successful */
734 if (NT_STATUS_IS_OK(result)) {
735 return True;
738 *type = SID_NAME_UNKNOWN;
739 *name = talloc_strdup(mem_ctx, name_deadbeef);
741 return False;
744 /* Free state information held for {set,get,end}{pw,gr}ent() functions */
746 void free_getent_state(struct getent_state *state)
748 struct getent_state *temp;
750 /* Iterate over state list */
752 temp = state;
754 while(temp != NULL) {
755 struct getent_state *next;
757 /* Free sam entries then list entry */
759 SAFE_FREE(state->sam_entries);
760 DLIST_REMOVE(state, state);
761 next = temp->next;
763 SAFE_FREE(temp);
764 temp = next;
768 /* Is this a domain which we may assume no DOMAIN\ prefix? */
770 static BOOL assume_domain(const char *domain)
772 /* never assume the domain on a standalone server */
774 if ( lp_server_role() == ROLE_STANDALONE )
775 return False;
777 /* domain member servers may possibly assume for the domain name */
779 if ( lp_server_role() == ROLE_DOMAIN_MEMBER ) {
780 if ( !strequal(lp_workgroup(), domain) )
781 return False;
783 if ( lp_winbind_use_default_domain() || lp_winbind_trusted_domains_only() )
784 return True;
787 /* only left with a domain controller */
789 if ( strequal(get_global_sam_name(), domain) ) {
790 return True;
793 return False;
796 /* Parse a string of the form DOMAIN\user into a domain and a user */
798 BOOL parse_domain_user(const char *domuser, fstring domain, fstring user)
800 char *p = strchr(domuser,*lp_winbind_separator());
802 if ( !p ) {
803 fstrcpy(user, domuser);
805 if ( assume_domain(lp_workgroup())) {
806 fstrcpy(domain, lp_workgroup());
807 } else {
808 return False;
810 } else {
811 fstrcpy(user, p+1);
812 fstrcpy(domain, domuser);
813 domain[PTR_DIFF(p, domuser)] = 0;
816 strupper_m(domain);
818 return True;
821 BOOL parse_domain_user_talloc(TALLOC_CTX *mem_ctx, const char *domuser,
822 char **domain, char **user)
824 fstring fstr_domain, fstr_user;
825 if (!parse_domain_user(domuser, fstr_domain, fstr_user)) {
826 return False;
828 *domain = talloc_strdup(mem_ctx, fstr_domain);
829 *user = talloc_strdup(mem_ctx, fstr_user);
830 return ((*domain != NULL) && (*user != NULL));
833 /* Ensure an incoming username from NSS is fully qualified. Replace the
834 incoming fstring with DOMAIN <separator> user. Returns the same
835 values as parse_domain_user() but also replaces the incoming username.
836 Used to ensure all names are fully qualified within winbindd.
837 Used by the NSS protocols of auth, chauthtok, logoff and ccache_ntlm_auth.
838 The protocol definitions of auth_crap, chng_pswd_auth_crap
839 really should be changed to use this instead of doing things
840 by hand. JRA. */
842 BOOL canonicalize_username(fstring username_inout, fstring domain, fstring user)
844 if (!parse_domain_user(username_inout, domain, user)) {
845 return False;
847 slprintf(username_inout, sizeof(fstring) - 1, "%s%c%s",
848 domain, *lp_winbind_separator(),
849 user);
850 return True;
854 Fill DOMAIN\\USERNAME entry accounting 'winbind use default domain' and
855 'winbind separator' options.
856 This means:
857 - omit DOMAIN when 'winbind use default domain = true' and DOMAIN is
858 lp_workgroup()
860 If we are a PDC or BDC, and this is for our domain, do likewise.
862 Also, if omit DOMAIN if 'winbind trusted domains only = true', as the
863 username is then unqualified in unix
865 We always canonicalize as UPPERCASE DOMAIN, lowercase username.
867 void fill_domain_username(fstring name, const char *domain, const char *user, BOOL can_assume)
869 fstring tmp_user;
871 fstrcpy(tmp_user, user);
872 strlower_m(tmp_user);
874 if (can_assume && assume_domain(domain)) {
875 strlcpy(name, tmp_user, sizeof(fstring));
876 } else {
877 slprintf(name, sizeof(fstring) - 1, "%s%c%s",
878 domain, *lp_winbind_separator(),
879 tmp_user);
884 * Winbindd socket accessor functions
887 char *get_winbind_priv_pipe_dir(void)
889 return lock_path(WINBINDD_PRIV_SOCKET_SUBDIR);
892 /* Open the winbindd socket */
894 static int _winbindd_socket = -1;
895 static int _winbindd_priv_socket = -1;
897 int open_winbindd_socket(void)
899 if (_winbindd_socket == -1) {
900 _winbindd_socket = create_pipe_sock(
901 WINBINDD_SOCKET_DIR, WINBINDD_SOCKET_NAME, 0755);
902 DEBUG(10, ("open_winbindd_socket: opened socket fd %d\n",
903 _winbindd_socket));
906 return _winbindd_socket;
909 int open_winbindd_priv_socket(void)
911 if (_winbindd_priv_socket == -1) {
912 _winbindd_priv_socket = create_pipe_sock(
913 get_winbind_priv_pipe_dir(), WINBINDD_SOCKET_NAME, 0750);
914 DEBUG(10, ("open_winbindd_priv_socket: opened socket fd %d\n",
915 _winbindd_priv_socket));
918 return _winbindd_priv_socket;
921 /* Close the winbindd socket */
923 void close_winbindd_socket(void)
925 if (_winbindd_socket != -1) {
926 DEBUG(10, ("close_winbindd_socket: closing socket fd %d\n",
927 _winbindd_socket));
928 close(_winbindd_socket);
929 _winbindd_socket = -1;
931 if (_winbindd_priv_socket != -1) {
932 DEBUG(10, ("close_winbindd_socket: closing socket fd %d\n",
933 _winbindd_priv_socket));
934 close(_winbindd_priv_socket);
935 _winbindd_priv_socket = -1;
940 * Client list accessor functions
943 static struct winbindd_cli_state *_client_list;
944 static int _num_clients;
946 /* Return list of all connected clients */
948 struct winbindd_cli_state *winbindd_client_list(void)
950 return _client_list;
953 /* Add a connection to the list */
955 void winbindd_add_client(struct winbindd_cli_state *cli)
957 DLIST_ADD(_client_list, cli);
958 _num_clients++;
961 /* Remove a client from the list */
963 void winbindd_remove_client(struct winbindd_cli_state *cli)
965 DLIST_REMOVE(_client_list, cli);
966 _num_clients--;
969 /* Close all open clients */
971 void winbindd_kill_all_clients(void)
973 struct winbindd_cli_state *cl = winbindd_client_list();
975 DEBUG(10, ("winbindd_kill_all_clients: going postal\n"));
977 while (cl) {
978 struct winbindd_cli_state *next;
980 next = cl->next;
981 winbindd_remove_client(cl);
982 cl = next;
986 /* Return number of open clients */
988 int winbindd_num_clients(void)
990 return _num_clients;
993 NTSTATUS lookup_usergroups_cached(struct winbindd_domain *domain,
994 TALLOC_CTX *mem_ctx,
995 const DOM_SID *user_sid,
996 uint32 *p_num_groups, DOM_SID **user_sids)
998 NET_USER_INFO_3 *info3 = NULL;
999 NTSTATUS status = NT_STATUS_NO_MEMORY;
1000 int i;
1001 size_t num_groups = 0;
1002 DOM_SID group_sid, primary_group;
1004 DEBUG(3,(": lookup_usergroups_cached\n"));
1006 *user_sids = NULL;
1007 num_groups = 0;
1008 *p_num_groups = 0;
1010 info3 = netsamlogon_cache_get(mem_ctx, user_sid);
1012 if (info3 == NULL) {
1013 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1016 if (info3->num_groups == 0) {
1017 SAFE_FREE(info3);
1018 return NT_STATUS_UNSUCCESSFUL;
1021 /* always add the primary group to the sid array */
1022 sid_compose(&primary_group, &info3->dom_sid.sid, info3->user_rid);
1024 if (!add_sid_to_array(mem_ctx, &primary_group, user_sids, &num_groups)) {
1025 SAFE_FREE(info3);
1026 return NT_STATUS_NO_MEMORY;
1029 for (i=0; i<info3->num_groups; i++) {
1030 sid_copy(&group_sid, &info3->dom_sid.sid);
1031 sid_append_rid(&group_sid, info3->gids[i].g_rid);
1033 if (!add_sid_to_array(mem_ctx, &group_sid, user_sids,
1034 &num_groups)) {
1035 SAFE_FREE(info3);
1036 return NT_STATUS_NO_MEMORY;
1040 SAFE_FREE(info3);
1041 *p_num_groups = num_groups;
1042 status = (user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1044 DEBUG(3,(": lookup_usergroups_cached succeeded\n"));
1046 return status;