2 Unix SMB/CIFS implementation.
4 Winbind daemon connection manager
6 Copyright (C) Tim Potter 2001
7 Copyright (C) Andrew Bartlett 2002
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.
25 We need to manage connections to domain controllers without having to
26 mess up the main winbindd code with other issues. The aim of the
27 connection manager is to:
29 - make connections to domain controllers and cache them
30 - re-establish connections when networks or servers go down
31 - centralise the policy on connection timeouts, domain controller
33 - manage re-entrancy for when winbindd becomes able to handle
34 multiple outstanding rpc requests
36 Why not have connection management as part of the rpc layer like tng?
37 Good question. This code may morph into libsmb/rpc_cache.c or something
38 like that but at the moment it's simply staying as part of winbind. I
39 think the TNG architecture of forcing every user of the rpc layer to use
40 the connection caching system is a bad idea. It should be an optional
41 method of using the routines.
43 The TNG design is quite good but I disagree with some aspects of the
51 - I'm pretty annoyed by all the make_nmb_name() stuff. It should be
52 moved down into another function.
54 - There needs to be a utility function in libsmb/namequery.c that does
57 - Take care when destroying cli_structs as they can be shared between
65 #define DBGC_CLASS DBGC_WINBIND
67 /* Global list of connections. Initially a DLIST but can become a hash
68 table or whatever later. */
70 struct winbindd_cm_conn {
71 struct winbindd_cm_conn *prev, *next;
75 size_t mutex_ref_count;
76 struct cli_state *cli;
80 static struct winbindd_cm_conn *cm_conns = NULL;
82 /* Get a domain controller name. Cache positive and negative lookups so we
83 don't go to the network too often when something is badly broken. */
85 #define GET_DC_NAME_CACHE_TIMEOUT 30 /* Seconds between dc lookups */
87 struct get_dc_name_cache {
91 struct get_dc_name_cache *prev, *next;
95 find the DC for a domain using methods appropriate for a ADS domain
97 static BOOL cm_ads_find_dc(const char *domain, struct in_addr *dc_ip, fstring srv_name)
100 const char *realm = domain;
102 if (strcasecmp(realm, lp_workgroup()) == 0)
105 ads = ads_init(realm, domain, NULL);
109 /* we don't need to bind, just connect */
110 ads->auth.flags |= ADS_AUTH_NO_BIND;
112 DEBUG(4,("cm_ads_find_dc: domain=%s\n", domain));
115 /* a full ads_connect() is actually overkill, as we don't srictly need
116 to do the SASL auth in order to get the info we need, but libads
117 doesn't offer a better way right now */
121 if (!ads->config.realm)
124 fstrcpy(srv_name, ads->config.ldap_server_name);
126 *dc_ip = ads->ldap_ip;
129 DEBUG(4,("cm_ads_find_dc: using server='%s' IP=%s\n",
130 srv_name, inet_ntoa(*dc_ip)));
137 static BOOL cm_get_dc_name(const char *domain, fstring srv_name, struct in_addr *ip_out)
139 static struct get_dc_name_cache *get_dc_name_cache;
140 struct get_dc_name_cache *dcc;
141 struct in_addr dc_ip;
144 /* Check the cache for previous lookups */
146 for (dcc = get_dc_name_cache; dcc; dcc = dcc->next) {
148 if (!strequal(domain, dcc->domain_name))
149 continue; /* Not our domain */
151 if ((time(NULL) - dcc->lookup_time) >
152 GET_DC_NAME_CACHE_TIMEOUT) {
154 /* Cache entry has expired, delete it */
156 DEBUG(10, ("get_dc_name_cache entry expired for %s\n", domain));
158 DLIST_REMOVE(get_dc_name_cache, dcc);
164 /* Return a positive or negative lookup for this domain */
166 if (dcc->srv_name[0]) {
167 DEBUG(10, ("returning positive get_dc_name_cache entry for %s\n", domain));
168 fstrcpy(srv_name, dcc->srv_name);
171 DEBUG(10, ("returning negative get_dc_name_cache entry for %s\n", domain));
176 /* Add cache entry for this lookup. */
178 DEBUG(10, ("Creating get_dc_name_cache entry for %s\n", domain));
180 if (!(dcc = (struct get_dc_name_cache *)
181 malloc(sizeof(struct get_dc_name_cache))))
186 fstrcpy(dcc->domain_name, domain);
187 dcc->lookup_time = time(NULL);
189 DLIST_ADD(get_dc_name_cache, dcc);
194 if (lp_security() == SEC_ADS)
195 ret = cm_ads_find_dc(domain, &dc_ip, srv_name);
198 /* fall back on rpc methods if the ADS methods fail */
199 ret = rpc_find_dc(domain, srv_name, &dc_ip);
205 /* We have a name so make the cache entry positive now */
206 fstrcpy(dcc->srv_name, srv_name);
208 DEBUG(3, ("cm_get_dc_name: Returning DC %s (%s) for domain %s\n", srv_name,
209 inet_ntoa(dc_ip), domain));
216 /* Choose between anonymous or authenticated connections. We need to use
217 an authenticated connection if DCs have the RestrictAnonymous registry
218 entry set > 0, or the "Additional restrictions for anonymous
219 connections" set in the win2k Local Security Policy.
221 Caller to free() result in domain, username, password
224 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
226 *username = secrets_fetch(SECRETS_AUTH_USER, NULL);
227 *domain = secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
228 *password = secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
230 if (*username && **username) {
232 if (!*domain || !**domain)
233 *domain = smb_xstrdup(lp_workgroup());
235 if (!*password || !**password)
236 *password = smb_xstrdup("");
238 DEBUG(3, ("IPC$ connections done by user %s\\%s\n",
239 *domain, *username));
242 DEBUG(3, ("IPC$ connections done anonymously\n"));
243 *username = smb_xstrdup("");
244 *domain = smb_xstrdup("");
245 *password = smb_xstrdup("");
249 /* Open a new smb pipe connection to a DC on a given domain. Cache
250 negative creation attempts so we don't try and connect to broken
251 machines too often. */
253 #define FAILED_CONNECTION_CACHE_TIMEOUT 30 /* Seconds between attempts */
255 struct failed_connection_cache {
260 struct failed_connection_cache *prev, *next;
263 static struct failed_connection_cache *failed_connection_cache;
265 /* Add an entry to the failed conneciton cache */
267 static void add_failed_connection_entry(struct winbindd_cm_conn *new_conn,
270 struct failed_connection_cache *fcc;
272 SMB_ASSERT(!NT_STATUS_IS_OK(result));
274 /* Check we already aren't in the cache */
276 for (fcc = failed_connection_cache; fcc; fcc = fcc->next) {
277 if (strequal(fcc->domain_name, new_conn->domain)) {
278 DEBUG(10, ("domain %s already tried and failed\n",
284 /* Create negative lookup cache entry for this domain and controller */
286 if (!(fcc = (struct failed_connection_cache *)
287 malloc(sizeof(struct failed_connection_cache)))) {
288 DEBUG(0, ("malloc failed in add_failed_connection_entry!\n"));
294 fstrcpy(fcc->domain_name, new_conn->domain);
295 fstrcpy(fcc->controller, new_conn->controller);
296 fcc->lookup_time = time(NULL);
297 fcc->nt_status = result;
299 DLIST_ADD(failed_connection_cache, fcc);
302 /* Open a connction to the remote server, cache failures for 30 seconds */
304 static NTSTATUS cm_open_connection(const char *domain, const int pipe_index,
305 struct winbindd_cm_conn *new_conn)
307 struct failed_connection_cache *fcc;
309 char *ipc_username, *ipc_domain, *ipc_password;
310 struct in_addr dc_ip;
316 fstrcpy(new_conn->domain, domain);
317 fstrcpy(new_conn->pipe_name, get_pipe_name_from_index(pipe_index));
319 /* Look for a domain controller for this domain. Negative results
320 are cached so don't bother applying the caching for this
321 function just yet. */
323 if (!cm_get_dc_name(domain, new_conn->controller, &dc_ip)) {
324 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
325 add_failed_connection_entry(new_conn, result);
329 /* Return false if we have tried to look up this domain and netbios
330 name before and failed. */
332 for (fcc = failed_connection_cache; fcc; fcc = fcc->next) {
334 if (!(strequal(domain, fcc->domain_name) &&
335 strequal(new_conn->controller, fcc->controller)))
336 continue; /* Not our domain */
338 if ((time(NULL) - fcc->lookup_time) >
339 FAILED_CONNECTION_CACHE_TIMEOUT) {
341 /* Cache entry has expired, delete it */
343 DEBUG(10, ("cm_open_connection cache entry expired for %s, %s\n", domain, new_conn->controller));
345 DLIST_REMOVE(failed_connection_cache, fcc);
351 /* The timeout hasn't expired yet so return false */
353 DEBUG(10, ("returning negative open_connection_cache entry for %s, %s\n", domain, new_conn->controller));
355 result = fcc->nt_status;
356 SMB_ASSERT(!NT_STATUS_IS_OK(result));
360 /* Initialise SMB connection */
362 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
364 DEBUG(5, ("connecting to %s from %s with username [%s]\\[%s]\n",
365 new_conn->controller, global_myname(), ipc_domain, ipc_username));
367 for (i = 0; retry && (i < 3); i++) {
369 if (!(got_mutex = secrets_named_mutex(new_conn->controller, WINBIND_SERVER_MUTEX_WAIT_TIME))) {
370 DEBUG(0,("cm_open_connection: mutex grab failed for %s\n", new_conn->controller));
371 result = NT_STATUS_POSSIBLE_DEADLOCK;
375 result = cli_full_connection(&new_conn->cli, global_myname(), new_conn->controller,
376 &dc_ip, 0, "IPC$", "IPC", ipc_username, ipc_domain,
377 ipc_password, CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK, &retry);
379 secrets_named_mutex_release(new_conn->controller);
381 if (NT_STATUS_IS_OK(result))
385 SAFE_FREE(ipc_username);
386 SAFE_FREE(ipc_domain);
387 SAFE_FREE(ipc_password);
389 if (!NT_STATUS_IS_OK(result)) {
390 add_failed_connection_entry(new_conn, result);
394 if ( !cli_nt_session_open (new_conn->cli, pipe_index) ) {
395 result = NT_STATUS_PIPE_NOT_AVAILABLE;
397 * only cache a failure if we are not trying to open the
398 * **win2k** specific lsarpc UUID. This could be an NT PDC
399 * and therefore a failure is normal. This should probably
400 * be abstracted to a check for 2k specific pipes and wondering
401 * if the PDC is an NT4 box. but since there is only one 2k
402 * specific UUID right now, i'm not going to bother. --jerry
404 if ( !is_win2k_pipe(pipe_index) )
405 add_failed_connection_entry(new_conn, result);
406 cli_shutdown(new_conn->cli);
413 /* Return true if a connection is still alive */
415 static BOOL connection_ok(struct winbindd_cm_conn *conn)
418 smb_panic("Invalid paramater passed to conneciton_ok(): conn was NULL!\n");
423 DEBUG(0, ("Connection to %s for domain %s (pipe %s) has NULL conn->cli!\n",
424 conn->controller, conn->domain, conn->pipe_name));
425 smb_panic("connection_ok: conn->cli was null!");
429 if (!conn->cli->initialised) {
430 DEBUG(0, ("Connection to %s for domain %s (pipe %s) was never initialised!\n",
431 conn->controller, conn->domain, conn->pipe_name));
432 smb_panic("connection_ok: conn->cli->initialised is False!");
436 if (conn->cli->fd == -1) {
437 DEBUG(3, ("Connection to %s for domain %s (pipe %s) has died or was never started (fd == -1)\n",
438 conn->controller, conn->domain, conn->pipe_name));
445 /* Get a connection to the remote DC and open the pipe. If there is already a connection, use that */
447 static NTSTATUS get_connection_from_cache(const char *domain, const char *pipe_name,
448 struct winbindd_cm_conn **conn_out)
450 struct winbindd_cm_conn *conn, conn_temp;
453 for (conn = cm_conns; conn; conn = conn->next) {
454 if (strequal(conn->domain, domain) &&
455 strequal(conn->pipe_name, pipe_name)) {
456 if (!connection_ok(conn)) {
458 cli_shutdown(conn->cli);
459 ZERO_STRUCT(conn_temp);
460 conn_temp.next = conn->next;
461 DLIST_REMOVE(cm_conns, conn);
463 conn = &conn_temp; /* Just to keep the loop moving */
471 if (!(conn = malloc(sizeof(*conn))))
472 return NT_STATUS_NO_MEMORY;
476 if (!NT_STATUS_IS_OK(result = cm_open_connection(domain, get_pipe_index(pipe_name), conn))) {
477 DEBUG(3, ("Could not open a connection to %s for %s (%s)\n",
478 domain, pipe_name, nt_errstr(result)));
482 DLIST_ADD(cm_conns, conn);
490 /**********************************************************************************
491 **********************************************************************************/
493 BOOL cm_check_for_native_mode_win2k( const char *domain )
496 struct winbindd_cm_conn conn;
504 if ( !NT_STATUS_IS_OK(result = cm_open_connection(domain, PI_LSARPC_DS, &conn)) ) {
505 DEBUG(5, ("cm_check_for_native_mode_win2k: Could not open a connection to %s for PIPE_LSARPC (%s)\n",
506 domain, nt_errstr(result)));
511 if ( !NT_STATUS_IS_OK(cli_ds_getprimarydominfo( conn.cli,
512 conn.cli->mem_ctx, DsRolePrimaryDomainInfoBasic, &ctr)) ) {
518 if ( (ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING)
519 && !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE) )
524 cli_shutdown( conn.cli );
531 /* Return a LSA policy handle on a domain */
533 CLI_POLICY_HND *cm_get_lsa_handle(const char *domain)
535 struct winbindd_cm_conn *conn;
536 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
538 static CLI_POLICY_HND hnd;
540 /* Look for existing connections */
542 if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_LSARPC, &conn)))
545 /* This *shitty* code needs scrapping ! JRA */
546 if (policy_handle_is_valid(&conn->pol)) {
552 result = cli_lsa_open_policy(conn->cli, conn->cli->mem_ctx, False,
553 des_access, &conn->pol);
555 if (!NT_STATUS_IS_OK(result)) {
556 /* Hit the cache code again. This cleans out the old connection and gets a new one */
557 if (conn->cli->fd == -1) { /* Try again, if the remote host disapeared */
558 if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_LSARPC, &conn)))
561 result = cli_lsa_open_policy(conn->cli, conn->cli->mem_ctx, False,
562 des_access, &conn->pol);
565 if (!NT_STATUS_IS_OK(result)) {
566 cli_shutdown(conn->cli);
567 DLIST_REMOVE(cm_conns, conn);
579 /* Return a SAM policy handle on a domain */
581 CLI_POLICY_HND *cm_get_sam_handle(char *domain)
583 struct winbindd_cm_conn *conn;
584 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
586 static CLI_POLICY_HND hnd;
588 /* Look for existing connections */
590 if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_SAMR, &conn)))
593 /* This *shitty* code needs scrapping ! JRA */
594 if (policy_handle_is_valid(&conn->pol)) {
599 result = cli_samr_connect(conn->cli, conn->cli->mem_ctx,
600 des_access, &conn->pol);
602 if (!NT_STATUS_IS_OK(result)) {
603 /* Hit the cache code again. This cleans out the old connection and gets a new one */
604 if (conn->cli->fd == -1) { /* Try again, if the remote host disapeared */
605 if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_SAMR, &conn)))
608 result = cli_samr_connect(conn->cli, conn->cli->mem_ctx,
609 des_access, &conn->pol);
612 if (!NT_STATUS_IS_OK(result)) {
613 cli_shutdown(conn->cli);
614 DLIST_REMOVE(cm_conns, conn);
626 #if 0 /* This code now *well* out of date */
628 /* Return a SAM domain policy handle on a domain */
630 CLI_POLICY_HND *cm_get_sam_dom_handle(char *domain, DOM_SID *domain_sid)
632 struct winbindd_cm_conn *conn, *basic_conn = NULL;
633 static CLI_POLICY_HND hnd;
635 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
637 /* Look for existing connections */
639 for (conn = cm_conns; conn; conn = conn->next) {
640 if (strequal(conn->domain, domain) &&
641 strequal(conn->pipe_name, PIPE_SAMR) &&
642 conn->pipe_data.samr.pipe_type == SAM_PIPE_DOM) {
644 if (!connection_ok(conn)) {
645 /* Shutdown cli? Free conn? Allow retry of DC? */
646 DLIST_REMOVE(cm_conns, conn);
654 /* Create a basic handle to open a domain handle from */
656 if (!cm_get_sam_handle(domain))
659 for (conn = cm_conns; conn; conn = conn->next) {
660 if (strequal(conn->domain, domain) &&
661 strequal(conn->pipe_name, PIPE_SAMR) &&
662 conn->pipe_data.samr.pipe_type == SAM_PIPE_BASIC)
666 if (!(conn = (struct winbindd_cm_conn *)
667 malloc(sizeof(struct winbindd_cm_conn))))
672 fstrcpy(conn->domain, basic_conn->domain);
673 fstrcpy(conn->controller, basic_conn->controller);
674 fstrcpy(conn->pipe_name, basic_conn->pipe_name);
676 conn->pipe_data.samr.pipe_type = SAM_PIPE_DOM;
677 conn->cli = basic_conn->cli;
679 result = cli_samr_open_domain(conn->cli, conn->cli->mem_ctx,
680 &basic_conn->pol, des_access,
681 domain_sid, &conn->pol);
683 if (!NT_STATUS_IS_OK(result))
688 DLIST_ADD(cm_conns, conn);
697 /* Return a SAM policy handle on a domain user */
699 CLI_POLICY_HND *cm_get_sam_user_handle(char *domain, DOM_SID *domain_sid,
702 struct winbindd_cm_conn *conn, *basic_conn = NULL;
703 static CLI_POLICY_HND hnd;
705 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
707 /* Look for existing connections */
709 for (conn = cm_conns; conn; conn = conn->next) {
710 if (strequal(conn->domain, domain) &&
711 strequal(conn->pipe_name, PIPE_SAMR) &&
712 conn->pipe_data.samr.pipe_type == SAM_PIPE_USER &&
713 conn->pipe_data.samr.rid == user_rid) {
715 if (!connection_ok(conn)) {
716 /* Shutdown cli? Free conn? Allow retry of DC? */
717 DLIST_REMOVE(cm_conns, conn);
725 /* Create a domain handle to open a user handle from */
727 if (!cm_get_sam_dom_handle(domain, domain_sid))
730 for (conn = cm_conns; conn; conn = conn->next) {
731 if (strequal(conn->domain, domain) &&
732 strequal(conn->pipe_name, PIPE_SAMR) &&
733 conn->pipe_data.samr.pipe_type == SAM_PIPE_DOM)
738 DEBUG(0, ("No domain sam handle was created!\n"));
742 if (!(conn = (struct winbindd_cm_conn *)
743 malloc(sizeof(struct winbindd_cm_conn))))
748 fstrcpy(conn->domain, basic_conn->domain);
749 fstrcpy(conn->controller, basic_conn->controller);
750 fstrcpy(conn->pipe_name, basic_conn->pipe_name);
752 conn->pipe_data.samr.pipe_type = SAM_PIPE_USER;
753 conn->cli = basic_conn->cli;
754 conn->pipe_data.samr.rid = user_rid;
756 result = cli_samr_open_user(conn->cli, conn->cli->mem_ctx,
757 &basic_conn->pol, des_access, user_rid,
760 if (!NT_STATUS_IS_OK(result))
765 DLIST_ADD(cm_conns, conn);
774 /* Return a SAM policy handle on a domain group */
776 CLI_POLICY_HND *cm_get_sam_group_handle(char *domain, DOM_SID *domain_sid,
779 struct winbindd_cm_conn *conn, *basic_conn = NULL;
780 static CLI_POLICY_HND hnd;
782 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
784 /* Look for existing connections */
786 for (conn = cm_conns; conn; conn = conn->next) {
787 if (strequal(conn->domain, domain) &&
788 strequal(conn->pipe_name, PIPE_SAMR) &&
789 conn->pipe_data.samr.pipe_type == SAM_PIPE_GROUP &&
790 conn->pipe_data.samr.rid == group_rid) {
792 if (!connection_ok(conn)) {
793 /* Shutdown cli? Free conn? Allow retry of DC? */
794 DLIST_REMOVE(cm_conns, conn);
802 /* Create a domain handle to open a user handle from */
804 if (!cm_get_sam_dom_handle(domain, domain_sid))
807 for (conn = cm_conns; conn; conn = conn->next) {
808 if (strequal(conn->domain, domain) &&
809 strequal(conn->pipe_name, PIPE_SAMR) &&
810 conn->pipe_data.samr.pipe_type == SAM_PIPE_DOM)
815 DEBUG(0, ("No domain sam handle was created!\n"));
819 if (!(conn = (struct winbindd_cm_conn *)
820 malloc(sizeof(struct winbindd_cm_conn))))
825 fstrcpy(conn->domain, basic_conn->domain);
826 fstrcpy(conn->controller, basic_conn->controller);
827 fstrcpy(conn->pipe_name, basic_conn->pipe_name);
829 conn->pipe_data.samr.pipe_type = SAM_PIPE_GROUP;
830 conn->cli = basic_conn->cli;
831 conn->pipe_data.samr.rid = group_rid;
833 result = cli_samr_open_group(conn->cli, conn->cli->mem_ctx,
834 &basic_conn->pol, des_access, group_rid,
837 if (!NT_STATUS_IS_OK(result))
842 DLIST_ADD(cm_conns, conn);
853 /* Get a handle on a netlogon pipe. This is a bit of a hack to re-use the
854 netlogon pipe as no handle is returned. */
856 NTSTATUS cm_get_netlogon_cli(const char *domain, const unsigned char *trust_passwd,
857 struct cli_state **cli)
859 NTSTATUS result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
860 struct winbindd_cm_conn *conn;
861 uint32 neg_flags = 0x000001ff;
866 return NT_STATUS_INVALID_PARAMETER;
868 /* Open an initial conection - keep the mutex. */
870 if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_NETLOGON, &conn)))
873 snprintf(lock_name, sizeof(lock_name), "NETLOGON\\%s", conn->controller);
875 if (!(got_mutex = secrets_named_mutex(lock_name, WINBIND_SERVER_MUTEX_WAIT_TIME))) {
876 DEBUG(0,("cm_get_netlogon_cli: mutex grab failed for %s\n", conn->controller));
879 result = cli_nt_setup_creds(conn->cli, get_sec_chan(), trust_passwd, &neg_flags, 2);
882 secrets_named_mutex_release(lock_name);
884 if (!NT_STATUS_IS_OK(result)) {
885 DEBUG(0, ("error connecting to domain password server: %s\n",
888 /* Hit the cache code again. This cleans out the old connection and gets a new one */
889 if (conn->cli->fd == -1) {
890 if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_NETLOGON, &conn)))
893 snprintf(lock_name, sizeof(lock_name), "NETLOGON\\%s", conn->controller);
894 if (!(got_mutex = secrets_named_mutex(lock_name, WINBIND_SERVER_MUTEX_WAIT_TIME))) {
895 DEBUG(0,("cm_get_netlogon_cli: mutex grab failed for %s\n", conn->controller));
899 result = cli_nt_setup_creds( conn->cli, get_sec_chan(),trust_passwd, &neg_flags, 2);
902 secrets_named_mutex_release(lock_name);
905 if (!NT_STATUS_IS_OK(result)) {
906 cli_shutdown(conn->cli);
907 DLIST_REMOVE(cm_conns, conn);
918 /* Dump the current connection status */
920 static void dump_conn_list(void)
922 struct winbindd_cm_conn *con;
924 DEBUG(0, ("\tDomain Controller Pipe\n"));
926 for(con = cm_conns; con; con = con->next) {
929 /* Display pipe info */
931 if (asprintf(&msg, "\t%-15s %-15s %-16s", con->domain, con->controller, con->pipe_name) < 0) {
932 DEBUG(0, ("Error: not enough memory!\n"));
934 DEBUG(0, ("%s\n", msg));
940 void winbindd_cm_status(void)
942 /* List open connections */
944 DEBUG(0, ("winbindd connection manager status:\n"));
949 DEBUG(0, ("\tNo active connections\n"));