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.
28 #define DBGC_CLASS DBGC_WINBIND
30 extern struct winbindd_methods cache_methods
;
31 extern struct winbindd_methods builtin_passdb_methods
;
32 extern struct winbindd_methods sam_passdb_methods
;
35 * @file winbindd_util.c
37 * Winbind daemon for NT domain authentication nss module.
41 /* The list of trusted domains. Note that the list can be deleted and
42 recreated using the init_domain_list() function so pointers to
43 individual winbindd_domain structures cannot be made. Keep a copy of
44 the domain name instead. */
46 static struct winbindd_domain
*_domain_list
;
49 When was the last scan of trusted domains done?
54 static time_t last_trustdom_scan
;
56 struct winbindd_domain
*domain_list(void)
60 if ((!_domain_list
) && (!init_domain_list())) {
61 smb_panic("Init_domain_list failed\n");
67 /* Free all entries in the trusted domain list */
69 void free_domain_list(void)
71 struct winbindd_domain
*domain
= _domain_list
;
74 struct winbindd_domain
*next
= domain
->next
;
76 DLIST_REMOVE(_domain_list
, domain
);
82 static BOOL
is_internal_domain(const DOM_SID
*sid
)
88 return sid_check_is_builtin(sid
);
90 return (sid_check_is_domain(sid
) || sid_check_is_builtin(sid
));
93 static BOOL
is_in_internal_domain(const DOM_SID
*sid
)
99 return sid_check_is_in_builtin(sid
);
101 return (sid_check_is_in_our_domain(sid
) || sid_check_is_in_builtin(sid
));
105 /* Add a trusted domain to our list of domains */
106 static struct winbindd_domain
*add_trusted_domain(const char *domain_name
, const char *alt_name
,
107 struct winbindd_methods
*methods
,
110 struct winbindd_domain
*domain
;
111 const char *alternative_name
= NULL
;
113 /* ignore alt_name if we are not in an AD domain */
115 if ( (lp_security() == SEC_ADS
) && alt_name
&& *alt_name
) {
116 alternative_name
= alt_name
;
119 /* We can't call domain_list() as this function is called from
120 init_domain_list() and we'll get stuck in a loop. */
121 for (domain
= _domain_list
; domain
; domain
= domain
->next
) {
122 if (strequal(domain_name
, domain
->name
) ||
123 strequal(domain_name
, domain
->alt_name
)) {
126 if (alternative_name
&& *alternative_name
) {
127 if (strequal(alternative_name
, domain
->name
) ||
128 strequal(alternative_name
, domain
->alt_name
)) {
133 if (is_null_sid(sid
)) {
135 } else if (sid_equal(sid
, &domain
->sid
)) {
141 /* Create new domain entry */
143 if ((domain
= SMB_MALLOC_P(struct winbindd_domain
)) == NULL
)
148 ZERO_STRUCTP(domain
);
150 fstrcpy(domain
->name
, domain_name
);
151 if (alternative_name
) {
152 fstrcpy(domain
->alt_name
, alternative_name
);
155 domain
->methods
= methods
;
156 domain
->backend
= NULL
;
157 domain
->internal
= is_internal_domain(sid
);
158 domain
->sequence_number
= DOM_SEQUENCE_NONE
;
159 domain
->last_seq_check
= 0;
160 domain
->initialized
= False
;
161 domain
->online
= is_internal_domain(sid
);
162 domain
->check_online_timeout
= 0;
164 sid_copy(&domain
->sid
, sid
);
167 /* Link to domain list */
168 DLIST_ADD(_domain_list
, domain
);
170 DEBUG(2,("Added domain %s %s %s\n",
171 domain
->name
, domain
->alt_name
,
172 &domain
->sid
?sid_string_static(&domain
->sid
):""));
177 /********************************************************************
178 rescan our domains looking for new trusted domains
179 ********************************************************************/
181 struct trustdom_state
{
183 struct winbindd_response
*response
;
186 static void trustdom_recv(void *private_data
, BOOL success
);
188 static void add_trusted_domains( struct winbindd_domain
*domain
)
191 struct winbindd_request
*request
;
192 struct winbindd_response
*response
;
194 struct trustdom_state
*state
;
196 mem_ctx
= talloc_init("add_trusted_domains");
197 if (mem_ctx
== NULL
) {
198 DEBUG(0, ("talloc_init failed\n"));
202 request
= TALLOC_ZERO_P(mem_ctx
, struct winbindd_request
);
203 response
= TALLOC_P(mem_ctx
, struct winbindd_response
);
204 state
= TALLOC_P(mem_ctx
, struct trustdom_state
);
206 if ((request
== NULL
) || (response
== NULL
) || (state
== NULL
)) {
207 DEBUG(0, ("talloc failed\n"));
208 talloc_destroy(mem_ctx
);
212 state
->mem_ctx
= mem_ctx
;
213 state
->response
= response
;
215 request
->length
= sizeof(*request
);
216 request
->cmd
= WINBINDD_LIST_TRUSTDOM
;
218 async_domain_request(mem_ctx
, domain
, request
, response
,
219 trustdom_recv
, state
);
222 static void trustdom_recv(void *private_data
, BOOL success
)
224 struct trustdom_state
*state
=
225 talloc_get_type_abort(private_data
, struct trustdom_state
);
226 struct winbindd_response
*response
= state
->response
;
229 if ((!success
) || (response
->result
!= WINBINDD_OK
)) {
230 DEBUG(1, ("Could not receive trustdoms\n"));
231 talloc_destroy(state
->mem_ctx
);
235 p
= (char *)response
->extra_data
.data
;
237 while ((p
!= NULL
) && (*p
!= '\0')) {
238 char *q
, *sidstr
, *alt_name
;
241 alt_name
= strchr(p
, '\\');
242 if (alt_name
== NULL
) {
243 DEBUG(0, ("Got invalid trustdom response\n"));
250 sidstr
= strchr(alt_name
, '\\');
251 if (sidstr
== NULL
) {
252 DEBUG(0, ("Got invalid trustdom response\n"));
259 q
= strchr(sidstr
, '\n');
263 if (!string_to_sid(&sid
, sidstr
)) {
264 /* Allow NULL sid for sibling domains */
265 if ( strcmp(sidstr
,"S-0-0") == 0) {
266 sid_copy( &sid
, &global_sid_NULL
);
268 DEBUG(0, ("Got invalid trustdom response\n"));
273 if (find_domain_from_name_noinit(p
) == NULL
) {
274 struct winbindd_domain
*domain
;
275 char *alternate_name
= NULL
;
277 /* use the real alt_name if we have one, else pass in NULL */
279 if ( !strequal( alt_name
, "(null)" ) )
280 alternate_name
= alt_name
;
282 domain
= add_trusted_domain(p
, alternate_name
,
285 setup_domain_child(domain
, &domain
->child
, NULL
);
292 SAFE_FREE(response
->extra_data
.data
);
293 talloc_destroy(state
->mem_ctx
);
296 /********************************************************************
297 Periodically we need to refresh the trusted domain cache for smbd
298 ********************************************************************/
300 void rescan_trusted_domains( void )
302 time_t now
= time(NULL
);
304 /* see if the time has come... */
306 if ((now
>= last_trustdom_scan
) &&
307 ((now
-last_trustdom_scan
) < WINBINDD_RESCAN_FREQ
) )
310 /* this will only add new domains we didn't already know about */
312 add_trusted_domains( find_our_domain() );
314 last_trustdom_scan
= now
;
319 struct init_child_state
{
321 struct winbindd_domain
*domain
;
322 struct winbindd_request
*request
;
323 struct winbindd_response
*response
;
324 void (*continuation
)(void *private_data
, BOOL success
);
328 static void init_child_recv(void *private_data
, BOOL success
);
329 static void init_child_getdc_recv(void *private_data
, BOOL success
);
331 enum winbindd_result
init_child_connection(struct winbindd_domain
*domain
,
332 void (*continuation
)(void *private_data
,
337 struct winbindd_request
*request
;
338 struct winbindd_response
*response
;
339 struct init_child_state
*state
;
340 struct winbindd_domain
*request_domain
;
342 mem_ctx
= talloc_init("init_child_connection");
343 if (mem_ctx
== NULL
) {
344 DEBUG(0, ("talloc_init failed\n"));
345 return WINBINDD_ERROR
;
348 request
= TALLOC_ZERO_P(mem_ctx
, struct winbindd_request
);
349 response
= TALLOC_P(mem_ctx
, struct winbindd_response
);
350 state
= TALLOC_P(mem_ctx
, struct init_child_state
);
352 if ((request
== NULL
) || (response
== NULL
) || (state
== NULL
)) {
353 DEBUG(0, ("talloc failed\n"));
354 TALLOC_FREE(mem_ctx
);
355 continuation(private_data
, False
);
356 return WINBINDD_ERROR
;
359 request
->length
= sizeof(*request
);
361 state
->mem_ctx
= mem_ctx
;
362 state
->domain
= domain
;
363 state
->request
= request
;
364 state
->response
= response
;
365 state
->continuation
= continuation
;
366 state
->private_data
= private_data
;
368 if (IS_DC
|| domain
->primary
) {
369 /* The primary domain has to find the DC name itself */
370 request
->cmd
= WINBINDD_INIT_CONNECTION
;
371 fstrcpy(request
->domain_name
, domain
->name
);
372 request
->data
.init_conn
.is_primary
= True
;
373 fstrcpy(request
->data
.init_conn
.dcname
, "");
374 async_request(mem_ctx
, &domain
->child
, request
, response
,
375 init_child_recv
, state
);
376 return WINBINDD_PENDING
;
379 /* This is *not* the primary domain, let's ask our DC about a DC
382 request
->cmd
= WINBINDD_GETDCNAME
;
383 fstrcpy(request
->domain_name
, domain
->name
);
385 request_domain
= find_our_domain();
387 async_domain_request(mem_ctx
, request_domain
, request
, response
,
388 init_child_getdc_recv
, state
);
389 return WINBINDD_PENDING
;
392 static void init_child_getdc_recv(void *private_data
, BOOL success
)
394 struct init_child_state
*state
=
395 talloc_get_type_abort(private_data
, struct init_child_state
);
396 const char *dcname
= "";
398 DEBUG(10, ("Received getdcname response\n"));
400 if (success
&& (state
->response
->result
== WINBINDD_OK
)) {
401 dcname
= state
->response
->data
.dc_name
;
404 state
->request
->cmd
= WINBINDD_INIT_CONNECTION
;
405 fstrcpy(state
->request
->domain_name
, state
->domain
->name
);
406 state
->request
->data
.init_conn
.is_primary
= False
;
407 fstrcpy(state
->request
->data
.init_conn
.dcname
, dcname
);
409 async_request(state
->mem_ctx
, &state
->domain
->child
,
410 state
->request
, state
->response
,
411 init_child_recv
, state
);
414 static void init_child_recv(void *private_data
, BOOL success
)
416 struct init_child_state
*state
=
417 talloc_get_type_abort(private_data
, struct init_child_state
);
419 DEBUG(5, ("Received child initialization response for domain %s\n",
420 state
->domain
->name
));
422 if ((!success
) || (state
->response
->result
!= WINBINDD_OK
)) {
423 DEBUG(3, ("Could not init child\n"));
424 state
->continuation(state
->private_data
, False
);
425 talloc_destroy(state
->mem_ctx
);
429 fstrcpy(state
->domain
->name
,
430 state
->response
->data
.domain_info
.name
);
431 fstrcpy(state
->domain
->alt_name
,
432 state
->response
->data
.domain_info
.alt_name
);
433 string_to_sid(&state
->domain
->sid
,
434 state
->response
->data
.domain_info
.sid
);
435 state
->domain
->native_mode
=
436 state
->response
->data
.domain_info
.native_mode
;
437 state
->domain
->active_directory
=
438 state
->response
->data
.domain_info
.active_directory
;
439 state
->domain
->sequence_number
=
440 state
->response
->data
.domain_info
.sequence_number
;
442 init_dc_connection(state
->domain
);
444 if (state
->continuation
!= NULL
)
445 state
->continuation(state
->private_data
, True
);
446 talloc_destroy(state
->mem_ctx
);
449 enum winbindd_result
winbindd_dual_init_connection(struct winbindd_domain
*domain
,
450 struct winbindd_cli_state
*state
)
452 /* Ensure null termination */
453 state
->request
.domain_name
454 [sizeof(state
->request
.domain_name
)-1]='\0';
455 state
->request
.data
.init_conn
.dcname
456 [sizeof(state
->request
.data
.init_conn
.dcname
)-1]='\0';
458 if (strlen(state
->request
.data
.init_conn
.dcname
) > 0) {
459 fstrcpy(domain
->dcname
, state
->request
.data
.init_conn
.dcname
);
462 init_dc_connection(domain
);
464 if (!domain
->initialized
) {
465 /* If we return error here we can't do any cached authentication,
466 but we may be in disconnected mode and can't initialize correctly.
467 Do what the previous code did and just return without initialization,
468 once we go online we'll re-initialize.
470 DEBUG(5, ("winbindd_dual_init_connection: %s returning without initialization "
471 "online = %d\n", domain
->name
, (int)domain
->online
));
474 fstrcpy(state
->response
.data
.domain_info
.name
, domain
->name
);
475 fstrcpy(state
->response
.data
.domain_info
.alt_name
, domain
->alt_name
);
476 fstrcpy(state
->response
.data
.domain_info
.sid
,
477 sid_string_static(&domain
->sid
));
479 state
->response
.data
.domain_info
.native_mode
480 = domain
->native_mode
;
481 state
->response
.data
.domain_info
.active_directory
482 = domain
->active_directory
;
483 state
->response
.data
.domain_info
.primary
485 state
->response
.data
.domain_info
.sequence_number
=
486 domain
->sequence_number
;
491 /* Look up global info for the winbind daemon */
492 BOOL
init_domain_list(void)
494 struct winbindd_domain
*domain
;
495 int role
= lp_server_role();
497 /* Free existing list */
500 /* Add ourselves as the first entry. */
502 if ( role
== ROLE_DOMAIN_MEMBER
) {
505 if (!secrets_fetch_domain_sid(lp_workgroup(), &our_sid
)) {
506 DEBUG(0, ("Could not fetch our SID - did we join?\n"));
510 domain
= add_trusted_domain( lp_workgroup(), lp_realm(),
511 &cache_methods
, &our_sid
);
512 domain
->primary
= True
;
513 setup_domain_child(domain
, &domain
->child
, NULL
);
515 /* Even in the parent winbindd we'll need to
516 talk to the DC, so try and see if we can
517 contact it. Theoretically this isn't neccessary
518 as the init_dc_connection() in init_child_recv()
519 will do this, but we can start detecting the DC
521 set_domain_online_request(domain
);
526 domain
= add_trusted_domain(get_global_sam_name(), NULL
,
527 &sam_passdb_methods
, get_global_sam_sid());
528 if ( role
!= ROLE_DOMAIN_MEMBER
) {
529 domain
->primary
= True
;
531 setup_domain_child(domain
, &domain
->child
, NULL
);
535 domain
= add_trusted_domain("BUILTIN", NULL
, &builtin_passdb_methods
,
536 &global_sid_Builtin
);
537 setup_domain_child(domain
, &domain
->child
, NULL
);
543 * Given a domain name, return the struct winbindd domain info for it
545 * @note Do *not* pass lp_workgroup() to this function. domain_list
546 * may modify it's value, and free that pointer. Instead, our local
547 * domain may be found by calling find_our_domain().
551 * @return The domain structure for the named domain, if it is working.
554 struct winbindd_domain
*find_domain_from_name_noinit(const char *domain_name
)
556 struct winbindd_domain
*domain
;
558 /* Search through list */
560 for (domain
= domain_list(); domain
!= NULL
; domain
= domain
->next
) {
561 if (strequal(domain_name
, domain
->name
) ||
562 (domain
->alt_name
[0] &&
563 strequal(domain_name
, domain
->alt_name
))) {
573 struct winbindd_domain
*find_domain_from_name(const char *domain_name
)
575 struct winbindd_domain
*domain
;
577 domain
= find_domain_from_name_noinit(domain_name
);
582 if (!domain
->initialized
)
583 init_dc_connection(domain
);
588 /* Given a domain sid, return the struct winbindd domain info for it */
590 struct winbindd_domain
*find_domain_from_sid_noinit(const DOM_SID
*sid
)
592 struct winbindd_domain
*domain
;
594 /* Search through list */
596 for (domain
= domain_list(); domain
!= NULL
; domain
= domain
->next
) {
597 if (sid_compare_domain(sid
, &domain
->sid
) == 0)
606 /* Given a domain sid, return the struct winbindd domain info for it */
608 struct winbindd_domain
*find_domain_from_sid(const DOM_SID
*sid
)
610 struct winbindd_domain
*domain
;
612 domain
= find_domain_from_sid_noinit(sid
);
617 if (!domain
->initialized
)
618 init_dc_connection(domain
);
623 struct winbindd_domain
*find_our_domain(void)
625 struct winbindd_domain
*domain
;
627 /* Search through list */
629 for (domain
= domain_list(); domain
!= NULL
; domain
= domain
->next
) {
634 smb_panic("Could not find our domain\n");
638 struct winbindd_domain
*find_root_domain(void)
640 struct winbindd_domain
*ours
= find_our_domain();
645 if ( strlen(ours
->forest_name
) == 0 )
648 return find_domain_from_name( ours
->forest_name
);
651 struct winbindd_domain
*find_builtin_domain(void)
654 struct winbindd_domain
*domain
;
656 string_to_sid(&sid
, "S-1-5-32");
657 domain
= find_domain_from_sid(&sid
);
660 smb_panic("Could not find BUILTIN domain\n");
665 /* Find the appropriate domain to lookup a name or SID */
667 struct winbindd_domain
*find_lookup_domain_from_sid(const DOM_SID
*sid
)
669 /* A DC can't ask the local smbd for remote SIDs, here winbindd is the
670 * one to contact the external DC's. On member servers the internal
671 * domains are different: These are part of the local SAM. */
673 DEBUG(10, ("find_lookup_domain_from_sid(%s)\n",
674 sid_string_static(sid
)));
676 if (IS_DC
|| is_internal_domain(sid
) || is_in_internal_domain(sid
)) {
677 DEBUG(10, ("calling find_domain_from_sid\n"));
678 return find_domain_from_sid(sid
);
681 /* On a member server a query for SID or name can always go to our
684 DEBUG(10, ("calling find_our_domain\n"));
685 return find_our_domain();
688 struct winbindd_domain
*find_lookup_domain_from_name(const char *domain_name
)
690 if (IS_DC
|| strequal(domain_name
, "BUILTIN") ||
691 strequal(domain_name
, get_global_sam_name()))
692 return find_domain_from_name_noinit(domain_name
);
694 return find_our_domain();
697 /* Lookup a sid in a domain from a name */
699 BOOL
winbindd_lookup_sid_by_name(TALLOC_CTX
*mem_ctx
,
700 struct winbindd_domain
*domain
,
701 const char *domain_name
,
702 const char *name
, DOM_SID
*sid
,
703 enum lsa_SidType
*type
)
708 result
= domain
->methods
->name_to_sid(domain
, mem_ctx
, domain_name
, name
, sid
, type
);
710 /* Return sid and type if lookup successful */
711 if (!NT_STATUS_IS_OK(result
)) {
712 *type
= SID_NAME_UNKNOWN
;
715 return NT_STATUS_IS_OK(result
);
719 * @brief Lookup a name in a domain from a sid.
721 * @param sid Security ID you want to look up.
722 * @param name On success, set to the name corresponding to @p sid.
723 * @param dom_name On success, set to the 'domain name' corresponding to @p sid.
724 * @param type On success, contains the type of name: alias, group or
726 * @retval True if the name exists, in which case @p name and @p type
727 * are set, otherwise False.
729 BOOL
winbindd_lookup_name_by_sid(TALLOC_CTX
*mem_ctx
,
733 enum lsa_SidType
*type
)
736 struct winbindd_domain
*domain
;
741 domain
= find_lookup_domain_from_sid(sid
);
744 DEBUG(1,("Can't find domain from sid\n"));
750 result
= domain
->methods
->sid_to_name(domain
, mem_ctx
, sid
, dom_name
, name
, type
);
752 /* Return name and type if successful */
754 if (NT_STATUS_IS_OK(result
)) {
758 *type
= SID_NAME_UNKNOWN
;
763 /* Free state information held for {set,get,end}{pw,gr}ent() functions */
765 void free_getent_state(struct getent_state
*state
)
767 struct getent_state
*temp
;
769 /* Iterate over state list */
773 while(temp
!= NULL
) {
774 struct getent_state
*next
= temp
->next
;
776 /* Free sam entries then list entry */
778 SAFE_FREE(state
->sam_entries
);
779 DLIST_REMOVE(state
, state
);
786 /* Is this a domain which we may assume no DOMAIN\ prefix? */
788 static BOOL
assume_domain(const char *domain
)
790 /* never assume the domain on a standalone server */
792 if ( lp_server_role() == ROLE_STANDALONE
)
795 /* domain member servers may possibly assume for the domain name */
797 if ( lp_server_role() == ROLE_DOMAIN_MEMBER
) {
798 if ( !strequal(lp_workgroup(), domain
) )
801 if ( lp_winbind_use_default_domain() || lp_winbind_trusted_domains_only() )
805 /* only left with a domain controller */
807 if ( strequal(get_global_sam_name(), domain
) ) {
814 /* Parse a string of the form DOMAIN\user into a domain and a user */
816 BOOL
parse_domain_user(const char *domuser
, fstring domain
, fstring user
)
818 char *p
= strchr(domuser
,*lp_winbind_separator());
821 fstrcpy(user
, domuser
);
823 if ( assume_domain(lp_workgroup())) {
824 fstrcpy(domain
, lp_workgroup());
830 fstrcpy(domain
, domuser
);
831 domain
[PTR_DIFF(p
, domuser
)] = 0;
839 BOOL
parse_domain_user_talloc(TALLOC_CTX
*mem_ctx
, const char *domuser
,
840 char **domain
, char **user
)
842 fstring fstr_domain
, fstr_user
;
843 if (!parse_domain_user(domuser
, fstr_domain
, fstr_user
)) {
846 *domain
= talloc_strdup(mem_ctx
, fstr_domain
);
847 *user
= talloc_strdup(mem_ctx
, fstr_user
);
848 return ((*domain
!= NULL
) && (*user
!= NULL
));
851 /* Ensure an incoming username from NSS is fully qualified. Replace the
852 incoming fstring with DOMAIN <separator> user. Returns the same
853 values as parse_domain_user() but also replaces the incoming username.
854 Used to ensure all names are fully qualified within winbindd.
855 Used by the NSS protocols of auth, chauthtok, logoff and ccache_ntlm_auth.
856 The protocol definitions of auth_crap, chng_pswd_auth_crap
857 really should be changed to use this instead of doing things
860 BOOL
canonicalize_username(fstring username_inout
, fstring domain
, fstring user
)
862 if (!parse_domain_user(username_inout
, domain
, user
)) {
865 slprintf(username_inout
, sizeof(fstring
) - 1, "%s%c%s",
866 domain
, *lp_winbind_separator(),
872 Fill DOMAIN\\USERNAME entry accounting 'winbind use default domain' and
873 'winbind separator' options.
875 - omit DOMAIN when 'winbind use default domain = true' and DOMAIN is
878 If we are a PDC or BDC, and this is for our domain, do likewise.
880 Also, if omit DOMAIN if 'winbind trusted domains only = true', as the
881 username is then unqualified in unix
883 We always canonicalize as UPPERCASE DOMAIN, lowercase username.
885 void fill_domain_username(fstring name
, const char *domain
, const char *user
, BOOL can_assume
)
889 fstrcpy(tmp_user
, user
);
890 strlower_m(tmp_user
);
892 if (can_assume
&& assume_domain(domain
)) {
893 strlcpy(name
, tmp_user
, sizeof(fstring
));
895 slprintf(name
, sizeof(fstring
) - 1, "%s%c%s",
896 domain
, *lp_winbind_separator(),
902 * Winbindd socket accessor functions
905 char *get_winbind_priv_pipe_dir(void)
907 return lock_path(WINBINDD_PRIV_SOCKET_SUBDIR
);
910 /* Open the winbindd socket */
912 static int _winbindd_socket
= -1;
913 static int _winbindd_priv_socket
= -1;
915 int open_winbindd_socket(void)
917 if (_winbindd_socket
== -1) {
918 _winbindd_socket
= create_pipe_sock(
919 WINBINDD_SOCKET_DIR
, WINBINDD_SOCKET_NAME
, 0755);
920 DEBUG(10, ("open_winbindd_socket: opened socket fd %d\n",
924 return _winbindd_socket
;
927 int open_winbindd_priv_socket(void)
929 if (_winbindd_priv_socket
== -1) {
930 _winbindd_priv_socket
= create_pipe_sock(
931 get_winbind_priv_pipe_dir(), WINBINDD_SOCKET_NAME
, 0750);
932 DEBUG(10, ("open_winbindd_priv_socket: opened socket fd %d\n",
933 _winbindd_priv_socket
));
936 return _winbindd_priv_socket
;
939 /* Close the winbindd socket */
941 void close_winbindd_socket(void)
943 if (_winbindd_socket
!= -1) {
944 DEBUG(10, ("close_winbindd_socket: closing socket fd %d\n",
946 close(_winbindd_socket
);
947 _winbindd_socket
= -1;
949 if (_winbindd_priv_socket
!= -1) {
950 DEBUG(10, ("close_winbindd_socket: closing socket fd %d\n",
951 _winbindd_priv_socket
));
952 close(_winbindd_priv_socket
);
953 _winbindd_priv_socket
= -1;
958 * Client list accessor functions
961 static struct winbindd_cli_state
*_client_list
;
962 static int _num_clients
;
964 /* Return list of all connected clients */
966 struct winbindd_cli_state
*winbindd_client_list(void)
971 /* Add a connection to the list */
973 void winbindd_add_client(struct winbindd_cli_state
*cli
)
975 DLIST_ADD(_client_list
, cli
);
979 /* Remove a client from the list */
981 void winbindd_remove_client(struct winbindd_cli_state
*cli
)
983 DLIST_REMOVE(_client_list
, cli
);
987 /* Close all open clients */
989 void winbindd_kill_all_clients(void)
991 struct winbindd_cli_state
*cl
= winbindd_client_list();
993 DEBUG(10, ("winbindd_kill_all_clients: going postal\n"));
996 struct winbindd_cli_state
*next
;
999 winbindd_remove_client(cl
);
1004 /* Return number of open clients */
1006 int winbindd_num_clients(void)
1008 return _num_clients
;
1011 NTSTATUS
lookup_usergroups_cached(struct winbindd_domain
*domain
,
1012 TALLOC_CTX
*mem_ctx
,
1013 const DOM_SID
*user_sid
,
1014 uint32
*p_num_groups
, DOM_SID
**user_sids
)
1016 NET_USER_INFO_3
*info3
= NULL
;
1017 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
1019 size_t num_groups
= 0;
1020 DOM_SID group_sid
, primary_group
;
1022 DEBUG(3,(": lookup_usergroups_cached\n"));
1028 info3
= netsamlogon_cache_get(mem_ctx
, user_sid
);
1030 if (info3
== NULL
) {
1031 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
1034 if (info3
->num_groups
== 0) {
1036 return NT_STATUS_UNSUCCESSFUL
;
1039 /* always add the primary group to the sid array */
1040 sid_compose(&primary_group
, &info3
->dom_sid
.sid
, info3
->user_rid
);
1042 if (!add_sid_to_array(mem_ctx
, &primary_group
, user_sids
, &num_groups
)) {
1044 return NT_STATUS_NO_MEMORY
;
1047 for (i
=0; i
<info3
->num_groups
; i
++) {
1048 sid_copy(&group_sid
, &info3
->dom_sid
.sid
);
1049 sid_append_rid(&group_sid
, info3
->gids
[i
].g_rid
);
1051 if (!add_sid_to_array(mem_ctx
, &group_sid
, user_sids
,
1054 return NT_STATUS_NO_MEMORY
;
1059 *p_num_groups
= num_groups
;
1060 status
= (user_sids
!= NULL
) ? NT_STATUS_OK
: NT_STATUS_NO_MEMORY
;
1062 DEBUG(3,(": lookup_usergroups_cached succeeded\n"));
1067 /*********************************************************************
1068 We use this to remove spaces from user and group names
1069 ********************************************************************/
1071 void ws_name_replace( char *name
, char replace
)
1073 char replace_char
[2] = { 0x0, 0x0 };
1075 if ( !lp_winbind_normalize_names() || (replace
== '\0') )
1078 replace_char
[0] = replace
;
1079 all_string_sub( name
, " ", replace_char
, 0 );
1084 /*********************************************************************
1085 We use this to do the inverse of ws_name_replace()
1086 ********************************************************************/
1088 void ws_name_return( char *name
, char replace
)
1090 char replace_char
[2] = { 0x0, 0x0 };
1092 if ( !lp_winbind_normalize_names() || (replace
== '\0') )
1095 replace_char
[0] = replace
;
1096 all_string_sub( name
, replace_char
, " ", 0 );