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 struct cli_state *cli;
79 static struct winbindd_cm_conn *cm_conns = NULL;
81 /* Get a domain controller name. Cache positive and negative lookups so we
82 don't go to the network too often when something is badly broken. */
84 #define GET_DC_NAME_CACHE_TIMEOUT 30 /* Seconds between dc lookups */
86 struct get_dc_name_cache {
90 struct get_dc_name_cache *prev, *next;
94 find the DC for a domain using methods appropriate for a ADS domain
96 static BOOL cm_ads_find_dc(const char *domain, struct in_addr *dc_ip, fstring srv_name)
99 const char *realm = domain;
101 if (strcasecmp(realm, lp_workgroup()) == 0)
104 ads = ads_init(realm, domain, NULL);
108 /* we don't need to bind, just connect */
109 ads->auth.flags |= ADS_AUTH_NO_BIND;
111 DEBUG(4,("cm_ads_find_dc: domain=%s\n", domain));
114 /* a full ads_connect() is actually overkill, as we don't srictly need
115 to do the SASL auth in order to get the info we need, but libads
116 doesn't offer a better way right now */
120 if (!ads->config.realm)
123 fstrcpy(srv_name, ads->config.ldap_server_name);
125 *dc_ip = ads->ldap_ip;
128 DEBUG(4,("cm_ads_find_dc: using server='%s' IP=%s\n",
129 srv_name, inet_ntoa(*dc_ip)));
136 static BOOL cm_get_dc_name(const char *domain, fstring srv_name, struct in_addr *ip_out)
138 static struct get_dc_name_cache *get_dc_name_cache;
139 struct get_dc_name_cache *dcc;
140 struct in_addr dc_ip;
143 /* Check the cache for previous lookups */
145 for (dcc = get_dc_name_cache; dcc; dcc = dcc->next) {
147 if (!strequal(domain, dcc->domain_name))
148 continue; /* Not our domain */
150 if ((time(NULL) - dcc->lookup_time) >
151 GET_DC_NAME_CACHE_TIMEOUT) {
153 /* Cache entry has expired, delete it */
155 DEBUG(10, ("get_dc_name_cache entry expired for %s\n", domain));
157 DLIST_REMOVE(get_dc_name_cache, dcc);
163 /* Return a positive or negative lookup for this domain */
165 if (dcc->srv_name[0]) {
166 DEBUG(10, ("returning positive get_dc_name_cache entry for %s\n", domain));
167 fstrcpy(srv_name, dcc->srv_name);
170 DEBUG(10, ("returning negative get_dc_name_cache entry for %s\n", domain));
175 /* Add cache entry for this lookup. */
177 DEBUG(10, ("Creating get_dc_name_cache entry for %s\n", domain));
179 if (!(dcc = (struct get_dc_name_cache *)
180 malloc(sizeof(struct get_dc_name_cache))))
185 fstrcpy(dcc->domain_name, domain);
186 dcc->lookup_time = time(NULL);
188 DLIST_ADD(get_dc_name_cache, dcc);
193 if (lp_security() == SEC_ADS)
194 ret = cm_ads_find_dc(domain, &dc_ip, srv_name);
197 /* fall back on rpc methods if the ADS methods fail */
198 ret = rpc_find_dc(domain, srv_name, &dc_ip);
204 /* We have a name so make the cache entry positive now */
205 fstrcpy(dcc->srv_name, srv_name);
207 DEBUG(3, ("cm_get_dc_name: Returning DC %s (%s) for domain %s\n", srv_name,
208 inet_ntoa(dc_ip), domain));
215 /* Choose between anonymous or authenticated connections. We need to use
216 an authenticated connection if DCs have the RestrictAnonymous registry
217 entry set > 0, or the "Additional restrictions for anonymous
218 connections" set in the win2k Local Security Policy.
220 Caller to free() result in domain, username, password
223 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
225 *username = secrets_fetch(SECRETS_AUTH_USER, NULL);
226 *domain = secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
227 *password = secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
229 if (*username && **username) {
231 if (!*domain || !**domain)
232 *domain = smb_xstrdup(lp_workgroup());
234 if (!*password || !**password)
235 *password = smb_xstrdup("");
237 DEBUG(3, ("IPC$ connections done by user %s\\%s\n",
238 *domain, *username));
241 DEBUG(3, ("IPC$ connections done anonymously\n"));
242 *username = smb_xstrdup("");
243 *domain = smb_xstrdup("");
244 *password = smb_xstrdup("");
248 /* Open a new smb pipe connection to a DC on a given domain. Cache
249 negative creation attempts so we don't try and connect to broken
250 machines too often. */
252 #define FAILED_CONNECTION_CACHE_TIMEOUT 30 /* Seconds between attempts */
254 struct failed_connection_cache {
259 struct failed_connection_cache *prev, *next;
262 static struct failed_connection_cache *failed_connection_cache;
264 /* Add an entry to the failed conneciton cache */
266 static void add_failed_connection_entry(struct winbindd_cm_conn *new_conn,
269 struct failed_connection_cache *fcc;
271 SMB_ASSERT(!NT_STATUS_IS_OK(result));
273 /* Check we already aren't in the cache */
275 for (fcc = failed_connection_cache; fcc; fcc = fcc->next) {
276 if (strequal(fcc->domain_name, new_conn->domain)) {
277 DEBUG(10, ("domain %s already tried and failed\n",
283 /* Create negative lookup cache entry for this domain and controller */
285 if (!(fcc = (struct failed_connection_cache *)
286 malloc(sizeof(struct failed_connection_cache)))) {
287 DEBUG(0, ("malloc failed in add_failed_connection_entry!\n"));
293 fstrcpy(fcc->domain_name, new_conn->domain);
294 fstrcpy(fcc->controller, new_conn->controller);
295 fcc->lookup_time = time(NULL);
296 fcc->nt_status = result;
298 DLIST_ADD(failed_connection_cache, fcc);
301 /* Open a connction to the remote server, cache failures for 30 seconds */
303 static NTSTATUS cm_open_connection(const char *domain, const int pipe_index,
304 struct winbindd_cm_conn *new_conn)
306 struct failed_connection_cache *fcc;
308 char *ipc_username, *ipc_domain, *ipc_password;
309 struct in_addr dc_ip;
315 fstrcpy(new_conn->domain, domain);
316 fstrcpy(new_conn->pipe_name, get_pipe_name_from_index(pipe_index));
318 /* Look for a domain controller for this domain. Negative results
319 are cached so don't bother applying the caching for this
320 function just yet. */
322 if (!cm_get_dc_name(domain, new_conn->controller, &dc_ip)) {
323 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
324 add_failed_connection_entry(new_conn, result);
328 /* Return false if we have tried to look up this domain and netbios
329 name before and failed. */
331 for (fcc = failed_connection_cache; fcc; fcc = fcc->next) {
333 if (!(strequal(domain, fcc->domain_name) &&
334 strequal(new_conn->controller, fcc->controller)))
335 continue; /* Not our domain */
337 if ((time(NULL) - fcc->lookup_time) >
338 FAILED_CONNECTION_CACHE_TIMEOUT) {
340 /* Cache entry has expired, delete it */
342 DEBUG(10, ("cm_open_connection cache entry expired for %s, %s\n", domain, new_conn->controller));
344 DLIST_REMOVE(failed_connection_cache, fcc);
350 /* The timeout hasn't expired yet so return false */
352 DEBUG(10, ("returning negative open_connection_cache entry for %s, %s\n", domain, new_conn->controller));
354 result = fcc->nt_status;
355 SMB_ASSERT(!NT_STATUS_IS_OK(result));
359 /* Initialise SMB connection */
361 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
363 DEBUG(5, ("connecting to %s from %s with username [%s]\\[%s]\n",
364 new_conn->controller, global_myname(), ipc_domain, ipc_username));
366 for (i = 0; retry && (i < 3); i++) {
368 result = cli_full_connection(&new_conn->cli, global_myname(), new_conn->controller,
369 &dc_ip, 0, "IPC$", "IPC", ipc_username, ipc_domain,
370 ipc_password, 0, &retry);
372 if (NT_STATUS_IS_OK(result))
376 SAFE_FREE(ipc_username);
377 SAFE_FREE(ipc_domain);
378 SAFE_FREE(ipc_password);
380 if (!NT_STATUS_IS_OK(result)) {
381 add_failed_connection_entry(new_conn, result);
385 if ( !cli_nt_session_open (new_conn->cli, pipe_index) ) {
386 result = NT_STATUS_PIPE_NOT_AVAILABLE;
388 * only cache a failure if we are not trying to open the
389 * **win2k** specific lsarpc UUID. This could be an NT PDC
390 * and therefore a failure is normal. This should probably
391 * be abstracted to a check for 2k specific pipes and wondering
392 * if the PDC is an NT4 box. but since there is only one 2k
393 * specific UUID right now, i'm not going to bother. --jerry
395 if ( !is_win2k_pipe(pipe_index) )
396 add_failed_connection_entry(new_conn, result);
397 cli_shutdown(new_conn->cli);
404 /* Return true if a connection is still alive */
406 static BOOL connection_ok(struct winbindd_cm_conn *conn)
409 smb_panic("Invalid paramater passed to conneciton_ok(): conn was NULL!\n");
414 DEBUG(0, ("Connection to %s for domain %s (pipe %s) has NULL conn->cli!\n",
415 conn->controller, conn->domain, conn->pipe_name));
416 smb_panic("connection_ok: conn->cli was null!");
420 if (!conn->cli->initialised) {
421 DEBUG(0, ("Connection to %s for domain %s (pipe %s) was never initialised!\n",
422 conn->controller, conn->domain, conn->pipe_name));
423 smb_panic("connection_ok: conn->cli->initialised is False!");
427 if (conn->cli->fd == -1) {
428 DEBUG(3, ("Connection to %s for domain %s (pipe %s) has died or was never started (fd == -1)\n",
429 conn->controller, conn->domain, conn->pipe_name));
436 /* Get a connection to the remote DC and open the pipe. If there is already a connection, use that */
438 static NTSTATUS get_connection_from_cache(const char *domain, const char *pipe_name, struct winbindd_cm_conn **conn_out)
440 struct winbindd_cm_conn *conn, conn_temp;
443 for (conn = cm_conns; conn; conn = conn->next) {
444 if (strequal(conn->domain, domain) &&
445 strequal(conn->pipe_name, pipe_name)) {
446 if (!connection_ok(conn)) {
448 cli_shutdown(conn->cli);
449 ZERO_STRUCT(conn_temp);
450 conn_temp.next = conn->next;
451 DLIST_REMOVE(cm_conns, conn);
453 conn = &conn_temp; /* Just to keep the loop moving */
461 if (!(conn = malloc(sizeof(*conn))))
462 return NT_STATUS_NO_MEMORY;
466 if (!NT_STATUS_IS_OK(result = cm_open_connection(domain, get_pipe_index(pipe_name), conn))) {
467 DEBUG(3, ("Could not open a connection to %s for %s (%s)\n",
468 domain, pipe_name, nt_errstr(result)));
472 DLIST_ADD(cm_conns, conn);
480 /**********************************************************************************
481 **********************************************************************************/
483 BOOL cm_check_for_native_mode_win2k( const char *domain )
486 struct winbindd_cm_conn conn;
494 if ( !NT_STATUS_IS_OK(result = cm_open_connection(domain, PI_LSARPC_DS, &conn)) ) {
495 DEBUG(5, ("cm_check_for_native_mode_win2k: Could not open a connection to %s for PIPE_LSARPC (%s)\n",
496 domain, nt_errstr(result)));
501 if ( !NT_STATUS_IS_OK(cli_ds_getprimarydominfo( conn.cli,
502 conn.cli->mem_ctx, DsRolePrimaryDomainInfoBasic, &ctr)) ) {
508 if ( (ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING)
509 && !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE) )
514 cli_shutdown( conn.cli );
521 /* Return a LSA policy handle on a domain */
523 CLI_POLICY_HND *cm_get_lsa_handle(const char *domain)
525 struct winbindd_cm_conn *conn;
526 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
528 static CLI_POLICY_HND hnd;
530 /* Look for existing connections */
532 if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_LSARPC, &conn)))
535 /* This *shitty* code needs scrapping ! JRA */
536 if (policy_handle_is_valid(&conn->pol)) {
542 result = cli_lsa_open_policy(conn->cli, conn->cli->mem_ctx, False,
543 des_access, &conn->pol);
545 if (!NT_STATUS_IS_OK(result)) {
546 /* Hit the cache code again. This cleans out the old connection and gets a new one */
547 if (conn->cli->fd == -1) { /* Try again, if the remote host disapeared */
548 if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_LSARPC, &conn)))
551 result = cli_lsa_open_policy(conn->cli, conn->cli->mem_ctx, False,
552 des_access, &conn->pol);
555 if (!NT_STATUS_IS_OK(result)) {
556 cli_shutdown(conn->cli);
557 DLIST_REMOVE(cm_conns, conn);
569 /* Return a SAM policy handle on a domain */
571 CLI_POLICY_HND *cm_get_sam_handle(char *domain)
573 struct winbindd_cm_conn *conn;
574 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
576 static CLI_POLICY_HND hnd;
578 /* Look for existing connections */
580 if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_SAMR, &conn)))
583 /* This *shitty* code needs scrapping ! JRA */
584 if (policy_handle_is_valid(&conn->pol)) {
589 result = cli_samr_connect(conn->cli, conn->cli->mem_ctx,
590 des_access, &conn->pol);
592 if (!NT_STATUS_IS_OK(result)) {
593 /* Hit the cache code again. This cleans out the old connection and gets a new one */
594 if (conn->cli->fd == -1) { /* Try again, if the remote host disapeared */
595 if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_SAMR, &conn)))
598 result = cli_samr_connect(conn->cli, conn->cli->mem_ctx,
599 des_access, &conn->pol);
602 if (!NT_STATUS_IS_OK(result)) {
603 cli_shutdown(conn->cli);
604 DLIST_REMOVE(cm_conns, conn);
616 #if 0 /* This code now *well* out of date */
618 /* Return a SAM domain policy handle on a domain */
620 CLI_POLICY_HND *cm_get_sam_dom_handle(char *domain, DOM_SID *domain_sid)
622 struct winbindd_cm_conn *conn, *basic_conn = NULL;
623 static CLI_POLICY_HND hnd;
625 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
627 /* Look for existing connections */
629 for (conn = cm_conns; conn; conn = conn->next) {
630 if (strequal(conn->domain, domain) &&
631 strequal(conn->pipe_name, PIPE_SAMR) &&
632 conn->pipe_data.samr.pipe_type == SAM_PIPE_DOM) {
634 if (!connection_ok(conn)) {
635 /* Shutdown cli? Free conn? Allow retry of DC? */
636 DLIST_REMOVE(cm_conns, conn);
644 /* Create a basic handle to open a domain handle from */
646 if (!cm_get_sam_handle(domain))
649 for (conn = cm_conns; conn; conn = conn->next) {
650 if (strequal(conn->domain, domain) &&
651 strequal(conn->pipe_name, PIPE_SAMR) &&
652 conn->pipe_data.samr.pipe_type == SAM_PIPE_BASIC)
656 if (!(conn = (struct winbindd_cm_conn *)
657 malloc(sizeof(struct winbindd_cm_conn))))
662 fstrcpy(conn->domain, basic_conn->domain);
663 fstrcpy(conn->controller, basic_conn->controller);
664 fstrcpy(conn->pipe_name, basic_conn->pipe_name);
666 conn->pipe_data.samr.pipe_type = SAM_PIPE_DOM;
667 conn->cli = basic_conn->cli;
669 result = cli_samr_open_domain(conn->cli, conn->cli->mem_ctx,
670 &basic_conn->pol, des_access,
671 domain_sid, &conn->pol);
673 if (!NT_STATUS_IS_OK(result))
678 DLIST_ADD(cm_conns, conn);
687 /* Return a SAM policy handle on a domain user */
689 CLI_POLICY_HND *cm_get_sam_user_handle(char *domain, DOM_SID *domain_sid,
692 struct winbindd_cm_conn *conn, *basic_conn = NULL;
693 static CLI_POLICY_HND hnd;
695 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
697 /* Look for existing connections */
699 for (conn = cm_conns; conn; conn = conn->next) {
700 if (strequal(conn->domain, domain) &&
701 strequal(conn->pipe_name, PIPE_SAMR) &&
702 conn->pipe_data.samr.pipe_type == SAM_PIPE_USER &&
703 conn->pipe_data.samr.rid == user_rid) {
705 if (!connection_ok(conn)) {
706 /* Shutdown cli? Free conn? Allow retry of DC? */
707 DLIST_REMOVE(cm_conns, conn);
715 /* Create a domain handle to open a user handle from */
717 if (!cm_get_sam_dom_handle(domain, domain_sid))
720 for (conn = cm_conns; conn; conn = conn->next) {
721 if (strequal(conn->domain, domain) &&
722 strequal(conn->pipe_name, PIPE_SAMR) &&
723 conn->pipe_data.samr.pipe_type == SAM_PIPE_DOM)
728 DEBUG(0, ("No domain sam handle was created!\n"));
732 if (!(conn = (struct winbindd_cm_conn *)
733 malloc(sizeof(struct winbindd_cm_conn))))
738 fstrcpy(conn->domain, basic_conn->domain);
739 fstrcpy(conn->controller, basic_conn->controller);
740 fstrcpy(conn->pipe_name, basic_conn->pipe_name);
742 conn->pipe_data.samr.pipe_type = SAM_PIPE_USER;
743 conn->cli = basic_conn->cli;
744 conn->pipe_data.samr.rid = user_rid;
746 result = cli_samr_open_user(conn->cli, conn->cli->mem_ctx,
747 &basic_conn->pol, des_access, user_rid,
750 if (!NT_STATUS_IS_OK(result))
755 DLIST_ADD(cm_conns, conn);
764 /* Return a SAM policy handle on a domain group */
766 CLI_POLICY_HND *cm_get_sam_group_handle(char *domain, DOM_SID *domain_sid,
769 struct winbindd_cm_conn *conn, *basic_conn = NULL;
770 static CLI_POLICY_HND hnd;
772 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
774 /* Look for existing connections */
776 for (conn = cm_conns; conn; conn = conn->next) {
777 if (strequal(conn->domain, domain) &&
778 strequal(conn->pipe_name, PIPE_SAMR) &&
779 conn->pipe_data.samr.pipe_type == SAM_PIPE_GROUP &&
780 conn->pipe_data.samr.rid == group_rid) {
782 if (!connection_ok(conn)) {
783 /* Shutdown cli? Free conn? Allow retry of DC? */
784 DLIST_REMOVE(cm_conns, conn);
792 /* Create a domain handle to open a user handle from */
794 if (!cm_get_sam_dom_handle(domain, domain_sid))
797 for (conn = cm_conns; conn; conn = conn->next) {
798 if (strequal(conn->domain, domain) &&
799 strequal(conn->pipe_name, PIPE_SAMR) &&
800 conn->pipe_data.samr.pipe_type == SAM_PIPE_DOM)
805 DEBUG(0, ("No domain sam handle was created!\n"));
809 if (!(conn = (struct winbindd_cm_conn *)
810 malloc(sizeof(struct winbindd_cm_conn))))
815 fstrcpy(conn->domain, basic_conn->domain);
816 fstrcpy(conn->controller, basic_conn->controller);
817 fstrcpy(conn->pipe_name, basic_conn->pipe_name);
819 conn->pipe_data.samr.pipe_type = SAM_PIPE_GROUP;
820 conn->cli = basic_conn->cli;
821 conn->pipe_data.samr.rid = group_rid;
823 result = cli_samr_open_group(conn->cli, conn->cli->mem_ctx,
824 &basic_conn->pol, des_access, group_rid,
827 if (!NT_STATUS_IS_OK(result))
832 DLIST_ADD(cm_conns, conn);
843 /* Get a handle on a netlogon pipe. This is a bit of a hack to re-use the
844 netlogon pipe as no handle is returned. */
846 NTSTATUS cm_get_netlogon_cli(const char *domain, const unsigned char *trust_passwd,
847 struct cli_state **cli)
849 NTSTATUS result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
850 struct winbindd_cm_conn *conn;
851 uint32 neg_flags = 0x000001ff;
853 struct in_addr dc_ip;
856 return NT_STATUS_INVALID_PARAMETER;
858 if (!cm_get_dc_name(domain, srv_name, &dc_ip))
859 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
861 if (!secrets_named_mutex(srv_name, 10)) {
862 DEBUG(0,("cm_get_netlogon_cli: mutex grab failed for %s\n", srv_name));
863 return NT_STATUS_POSSIBLE_DEADLOCK;
866 /* Open an initial conection */
868 if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_NETLOGON, &conn)))
871 result = cli_nt_setup_creds(conn->cli, get_sec_chan(), trust_passwd, &neg_flags, 2);
873 secrets_named_mutex_release(srv_name);
875 if (!NT_STATUS_IS_OK(result)) {
876 DEBUG(0, ("error connecting to domain password server: %s\n",
879 /* Hit the cache code again. This cleans out the old connection and gets a new one */
880 if (conn->cli->fd == -1) {
882 if (!secrets_named_mutex(srv_name, 10)) {
883 DEBUG(0,("cm_get_netlogon_cli: mutex grab failed for %s\n", srv_name));
884 return NT_STATUS_POSSIBLE_DEADLOCK;
887 if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_NETLOGON, &conn)))
891 result = cli_nt_setup_creds( conn->cli, get_sec_chan(),trust_passwd, &neg_flags, 2);
893 secrets_named_mutex_release(srv_name);
896 if (!NT_STATUS_IS_OK(result)) {
897 cli_shutdown(conn->cli);
898 DLIST_REMOVE(cm_conns, conn);
909 /* Dump the current connection status */
911 static void dump_conn_list(void)
913 struct winbindd_cm_conn *con;
915 DEBUG(0, ("\tDomain Controller Pipe\n"));
917 for(con = cm_conns; con; con = con->next) {
920 /* Display pipe info */
922 if (asprintf(&msg, "\t%-15s %-15s %-16s", con->domain, con->controller, con->pipe_name) < 0) {
923 DEBUG(0, ("Error: not enough memory!\n"));
925 DEBUG(0, ("%s\n", msg));
931 void winbindd_cm_status(void)
933 /* List open connections */
935 DEBUG(0, ("winbindd connection manager status:\n"));
940 DEBUG(0, ("\tNo active connections\n"));