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;
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) {
106 ads = ads_init(realm, domain, NULL);
111 /* we don't need to bind, just connect */
112 ads->auth.flags |= ADS_AUTH_NO_BIND;
114 DEBUG(4,("cm_ads_find_dc: domain=%s\n", domain));
117 /* a full ads_connect() is actually overkill, as we don't srictly need
118 to do the SASL auth in order to get the info we need, but libads
119 doesn't offer a better way right now */
123 if (!ads->config.realm) {
127 fstrcpy(srv_name, ads->config.ldap_server_name);
129 *dc_ip = ads->ldap_ip;
132 DEBUG(4,("cm_ads_find_dc: using server='%s' IP=%s\n",
133 srv_name, inet_ntoa(*dc_ip)));
139 find the DC for a domain using methods appropriate for a RPC domain
141 static BOOL cm_rpc_find_dc(const char *domain, struct in_addr *dc_ip, fstring srv_name)
143 struct in_addr *ip_list = NULL;
146 if (!get_dc_list(domain, &ip_list, &count)) {
147 struct in_addr pdc_ip;
149 if (!get_pdc_ip(domain, &pdc_ip)) {
150 DEBUG(3, ("Could not look up any DCs for domain %s\n",
155 ip_list = (struct in_addr *)malloc(sizeof(struct in_addr));
164 /* Pick a nice close server */
166 qsort(ip_list, count, sizeof(struct in_addr), QSORT_CAST ip_compare);
169 for (i = 0; i < count; i++) {
170 if (is_zero_ip(ip_list[i]))
173 if (name_status_find(domain, 0x1c, 0x20, ip_list[i], srv_name)) {
187 static BOOL cm_get_dc_name(const char *domain, fstring srv_name, struct in_addr *ip_out)
189 static struct get_dc_name_cache *get_dc_name_cache;
190 struct get_dc_name_cache *dcc;
191 struct in_addr dc_ip;
194 /* Check the cache for previous lookups */
196 for (dcc = get_dc_name_cache; dcc; dcc = dcc->next) {
198 if (!strequal(domain, dcc->domain_name))
199 continue; /* Not our domain */
201 if ((time(NULL) - dcc->lookup_time) >
202 GET_DC_NAME_CACHE_TIMEOUT) {
204 /* Cache entry has expired, delete it */
206 DEBUG(10, ("get_dc_name_cache entry expired for %s\n", domain));
208 DLIST_REMOVE(get_dc_name_cache, dcc);
214 /* Return a positive or negative lookup for this domain */
216 if (dcc->srv_name[0]) {
217 DEBUG(10, ("returning positive get_dc_name_cache entry for %s\n", domain));
218 fstrcpy(srv_name, dcc->srv_name);
221 DEBUG(10, ("returning negative get_dc_name_cache entry for %s\n", domain));
226 /* Add cache entry for this lookup. */
228 DEBUG(10, ("Creating get_dc_name_cache entry for %s\n", domain));
230 if (!(dcc = (struct get_dc_name_cache *)
231 malloc(sizeof(struct get_dc_name_cache))))
236 fstrcpy(dcc->domain_name, domain);
237 dcc->lookup_time = time(NULL);
239 DLIST_ADD(get_dc_name_cache, dcc);
244 if (lp_security() == SEC_ADS) {
245 ret = cm_ads_find_dc(domain, &dc_ip, srv_name);
248 /* fall back on rpc methods if the ADS methods fail */
249 ret = cm_rpc_find_dc(domain, &dc_ip, srv_name);
256 /* We have a name so make the cache entry positive now */
257 fstrcpy(dcc->srv_name, srv_name);
259 DEBUG(3, ("cm_get_dc_name: Returning DC %s (%s) for domain %s\n", srv_name,
260 inet_ntoa(dc_ip), domain));
267 /* Choose between anonymous or authenticated connections. We need to use
268 an authenticated connection if DCs have the RestrictAnonymous registry
269 entry set > 0, or the "Additional restrictions for anonymous
270 connections" set in the win2k Local Security Policy.
272 Caller to free() result in domain, username, password
275 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
277 *username = secrets_fetch(SECRETS_AUTH_USER, NULL);
278 *domain = secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
279 *password = secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
281 if (*username && **username) {
283 if (!*domain || !**domain)
284 *domain = smb_xstrdup(lp_workgroup());
286 if (!*password || !**password)
287 *password = smb_xstrdup("");
289 DEBUG(3, ("IPC$ connections done by user %s\\%s\n",
290 *domain, *username));
293 DEBUG(3, ("IPC$ connections done anonymously\n"));
294 *username = smb_xstrdup("");
295 *domain = smb_xstrdup("");
296 *password = smb_xstrdup("");
300 /* Open a new smb pipe connection to a DC on a given domain. Cache
301 negative creation attempts so we don't try and connect to broken
302 machines too often. */
304 #define FAILED_CONNECTION_CACHE_TIMEOUT 30 /* Seconds between attempts */
306 struct failed_connection_cache {
311 struct failed_connection_cache *prev, *next;
314 static struct failed_connection_cache *failed_connection_cache;
316 /* Add an entry to the failed conneciton cache */
318 static void add_failed_connection_entry(struct winbindd_cm_conn *new_conn,
321 struct failed_connection_cache *fcc;
323 SMB_ASSERT(!NT_STATUS_IS_OK(result));
325 /* Check we already aren't in the cache */
327 for (fcc = failed_connection_cache; fcc; fcc = fcc->next) {
328 if (strequal(fcc->domain_name, new_conn->domain)) {
329 DEBUG(10, ("domain %s already tried and failed\n",
335 /* Create negative lookup cache entry for this domain and controller */
337 if (!(fcc = (struct failed_connection_cache *)
338 malloc(sizeof(struct failed_connection_cache)))) {
339 DEBUG(0, ("malloc failed in add_failed_connection_entry!\n"));
345 fstrcpy(fcc->domain_name, new_conn->domain);
346 fstrcpy(fcc->controller, new_conn->controller);
347 fcc->lookup_time = time(NULL);
348 fcc->nt_status = result;
350 DLIST_ADD(failed_connection_cache, fcc);
353 /* Open a connction to the remote server, cache failures for 30 seconds */
355 static NTSTATUS cm_open_connection(const char *domain, const int pipe_index,
356 struct winbindd_cm_conn *new_conn)
358 struct failed_connection_cache *fcc;
360 char *ipc_username, *ipc_domain, *ipc_password;
361 struct in_addr dc_ip;
367 fstrcpy(new_conn->domain, domain);
368 fstrcpy(new_conn->pipe_name, get_pipe_name_from_index(pipe_index));
370 /* Look for a domain controller for this domain. Negative results
371 are cached so don't bother applying the caching for this
372 function just yet. */
374 if (!cm_get_dc_name(domain, new_conn->controller, &dc_ip)) {
375 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
376 add_failed_connection_entry(new_conn, result);
380 /* Return false if we have tried to look up this domain and netbios
381 name before and failed. */
383 for (fcc = failed_connection_cache; fcc; fcc = fcc->next) {
385 if (!(strequal(domain, fcc->domain_name) &&
386 strequal(new_conn->controller, fcc->controller)))
387 continue; /* Not our domain */
389 if ((time(NULL) - fcc->lookup_time) >
390 FAILED_CONNECTION_CACHE_TIMEOUT) {
392 /* Cache entry has expired, delete it */
394 DEBUG(10, ("cm_open_connection cache entry expired for %s, %s\n", domain, new_conn->controller));
396 DLIST_REMOVE(failed_connection_cache, fcc);
402 /* The timeout hasn't expired yet so return false */
404 DEBUG(10, ("returning negative open_connection_cache entry for %s, %s\n", domain, new_conn->controller));
406 result = fcc->nt_status;
407 SMB_ASSERT(!NT_STATUS_IS_OK(result));
411 /* Initialise SMB connection */
413 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
415 DEBUG(5, ("connecting to %s from %s with username [%s]\\[%s]\n",
416 new_conn->controller, global_myname(), ipc_domain, ipc_username));
418 for (i = 0; retry && (i < 3); i++) {
420 if (!secrets_named_mutex(new_conn->controller, 10)) {
421 DEBUG(0,("cm_open_connection: mutex grab failed for %s\n", new_conn->controller));
425 result = cli_full_connection(&new_conn->cli, global_myname(), new_conn->controller,
426 &dc_ip, 0, "IPC$", "IPC", ipc_username, ipc_domain,
427 ipc_password, 0, &retry);
429 secrets_named_mutex_release(new_conn->controller);
431 if (NT_STATUS_IS_OK(result))
435 SAFE_FREE(ipc_username);
436 SAFE_FREE(ipc_domain);
437 SAFE_FREE(ipc_password);
439 if (!NT_STATUS_IS_OK(result)) {
440 add_failed_connection_entry(new_conn, result);
444 if ( !cli_nt_session_open (new_conn->cli, pipe_index) ) {
445 result = NT_STATUS_PIPE_NOT_AVAILABLE;
447 * only cache a failure if we are not trying to open the
448 * **win2k** specific lsarpc UUID. This could be an NT PDC
449 * and therefore a failure is normal. This should probably
450 * be abstracted to a check for 2k specific pipes and wondering
451 * if the PDC is an NT4 box. but since there is only one 2k
452 * specific UUID right now, i'm not going to bother. --jerry
454 if ( !is_win2k_pipe(pipe_index) )
455 add_failed_connection_entry(new_conn, result);
456 cli_shutdown(new_conn->cli);
463 /* Return true if a connection is still alive */
465 static BOOL connection_ok(struct winbindd_cm_conn *conn)
468 smb_panic("Invalid paramater passed to conneciton_ok(): conn was NULL!\n");
473 DEBUG(0, ("Connection to %s for domain %s (pipe %s) has NULL conn->cli!\n",
474 conn->controller, conn->domain, conn->pipe_name));
475 smb_panic("connection_ok: conn->cli was null!");
479 if (!conn->cli->initialised) {
480 DEBUG(0, ("Connection to %s for domain %s (pipe %s) was never initialised!\n",
481 conn->controller, conn->domain, conn->pipe_name));
482 smb_panic("connection_ok: conn->cli->initialised is False!");
486 if (conn->cli->fd == -1) {
487 DEBUG(3, ("Connection to %s for domain %s (pipe %s) has died or was never started (fd == -1)\n",
488 conn->controller, conn->domain, conn->pipe_name));
495 /* Get a connection to the remote DC and open the pipe. If there is already a connection, use that */
497 static NTSTATUS get_connection_from_cache(const char *domain, const char *pipe_name, struct winbindd_cm_conn **conn_out)
499 struct winbindd_cm_conn *conn, conn_temp;
502 for (conn = cm_conns; conn; conn = conn->next) {
503 if (strequal(conn->domain, domain) &&
504 strequal(conn->pipe_name, pipe_name)) {
505 if (!connection_ok(conn)) {
507 cli_shutdown(conn->cli);
509 ZERO_STRUCT(conn_temp);
510 conn_temp.next = conn->next;
511 DLIST_REMOVE(cm_conns, conn);
513 conn = &conn_temp; /* Just to keep the loop moving */
521 if (!(conn = malloc(sizeof(*conn))))
522 return NT_STATUS_NO_MEMORY;
526 if (!NT_STATUS_IS_OK(result = cm_open_connection(domain, get_pipe_index(pipe_name), conn))) {
527 DEBUG(3, ("Could not open a connection to %s for %s (%s)\n",
528 domain, pipe_name, nt_errstr(result)));
532 DLIST_ADD(cm_conns, conn);
540 /**********************************************************************************
541 **********************************************************************************/
543 BOOL cm_check_for_native_mode_win2k( const char *domain )
546 struct winbindd_cm_conn conn;
554 if ( !NT_STATUS_IS_OK(result = cm_open_connection(domain, PI_LSARPC_DS, &conn)) )
556 DEBUG(5, ("cm_check_for_native_mode_win2k: Could not open a connection to %s for PIPE_LSARPC (%s)\n",
557 domain, nt_errstr(result)));
562 if ( !NT_STATUS_IS_OK(cli_ds_getprimarydominfo( conn.cli,
563 conn.cli->mem_ctx, DsRolePrimaryDomainInfoBasic, &ctr)) )
570 if ( (ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING)
571 && !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE) )
578 cli_shutdown( conn.cli );
585 /* Return a LSA policy handle on a domain */
587 CLI_POLICY_HND *cm_get_lsa_handle(const char *domain)
589 struct winbindd_cm_conn *conn;
590 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
592 static CLI_POLICY_HND hnd;
594 /* Look for existing connections */
596 if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_LSARPC, &conn))) {
600 /* This *shitty* code needs scrapping ! JRA */
601 if (policy_handle_is_valid(&conn->pol)) {
607 result = cli_lsa_open_policy(conn->cli, conn->cli->mem_ctx, False,
608 des_access, &conn->pol);
610 if (!NT_STATUS_IS_OK(result)) {
611 /* Hit the cache code again. This cleans out the old connection and gets a new one */
612 if (conn->cli->fd == -1) { /* Try again, if the remote host disapeared */
613 if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_LSARPC, &conn))) {
617 result = cli_lsa_open_policy(conn->cli, conn->cli->mem_ctx, False,
618 des_access, &conn->pol);
621 if (!NT_STATUS_IS_OK(result)) {
622 cli_shutdown(conn->cli);
623 DLIST_REMOVE(cm_conns, conn);
635 /* Return a SAM policy handle on a domain */
637 CLI_POLICY_HND *cm_get_sam_handle(char *domain)
639 struct winbindd_cm_conn *conn;
640 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
642 static CLI_POLICY_HND hnd;
644 /* Look for existing connections */
646 if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_SAMR, &conn))) {
650 /* This *shitty* code needs scrapping ! JRA */
651 if (policy_handle_is_valid(&conn->pol)) {
656 result = cli_samr_connect(conn->cli, conn->cli->mem_ctx,
657 des_access, &conn->pol);
659 if (!NT_STATUS_IS_OK(result)) {
660 /* Hit the cache code again. This cleans out the old connection and gets a new one */
661 if (conn->cli->fd == -1) { /* Try again, if the remote host disapeared */
662 if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_SAMR, &conn))) {
666 result = cli_samr_connect(conn->cli, conn->cli->mem_ctx,
667 des_access, &conn->pol);
670 if (!NT_STATUS_IS_OK(result)) {
671 cli_shutdown(conn->cli);
672 DLIST_REMOVE(cm_conns, conn);
684 #if 0 /* This code now *well* out of date */
686 /* Return a SAM domain policy handle on a domain */
688 CLI_POLICY_HND *cm_get_sam_dom_handle(char *domain, DOM_SID *domain_sid)
690 struct winbindd_cm_conn *conn, *basic_conn = NULL;
691 static CLI_POLICY_HND hnd;
693 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
695 /* Look for existing connections */
697 for (conn = cm_conns; conn; conn = conn->next) {
698 if (strequal(conn->domain, domain) &&
699 strequal(conn->pipe_name, PIPE_SAMR) &&
700 conn->pipe_data.samr.pipe_type == SAM_PIPE_DOM) {
702 if (!connection_ok(conn)) {
703 /* Shutdown cli? Free conn? Allow retry of DC? */
704 DLIST_REMOVE(cm_conns, conn);
712 /* Create a basic handle to open a domain handle from */
714 if (!cm_get_sam_handle(domain))
717 for (conn = cm_conns; conn; conn = conn->next) {
718 if (strequal(conn->domain, domain) &&
719 strequal(conn->pipe_name, PIPE_SAMR) &&
720 conn->pipe_data.samr.pipe_type == SAM_PIPE_BASIC)
724 if (!(conn = (struct winbindd_cm_conn *)
725 malloc(sizeof(struct winbindd_cm_conn))))
730 fstrcpy(conn->domain, basic_conn->domain);
731 fstrcpy(conn->controller, basic_conn->controller);
732 fstrcpy(conn->pipe_name, basic_conn->pipe_name);
734 conn->pipe_data.samr.pipe_type = SAM_PIPE_DOM;
735 conn->cli = basic_conn->cli;
737 result = cli_samr_open_domain(conn->cli, conn->cli->mem_ctx,
738 &basic_conn->pol, des_access,
739 domain_sid, &conn->pol);
741 if (!NT_STATUS_IS_OK(result))
746 DLIST_ADD(cm_conns, conn);
755 /* Return a SAM policy handle on a domain user */
757 CLI_POLICY_HND *cm_get_sam_user_handle(char *domain, DOM_SID *domain_sid,
760 struct winbindd_cm_conn *conn, *basic_conn = NULL;
761 static CLI_POLICY_HND hnd;
763 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
765 /* Look for existing connections */
767 for (conn = cm_conns; conn; conn = conn->next) {
768 if (strequal(conn->domain, domain) &&
769 strequal(conn->pipe_name, PIPE_SAMR) &&
770 conn->pipe_data.samr.pipe_type == SAM_PIPE_USER &&
771 conn->pipe_data.samr.rid == user_rid) {
773 if (!connection_ok(conn)) {
774 /* Shutdown cli? Free conn? Allow retry of DC? */
775 DLIST_REMOVE(cm_conns, conn);
783 /* Create a domain handle to open a user handle from */
785 if (!cm_get_sam_dom_handle(domain, domain_sid))
788 for (conn = cm_conns; conn; conn = conn->next) {
789 if (strequal(conn->domain, domain) &&
790 strequal(conn->pipe_name, PIPE_SAMR) &&
791 conn->pipe_data.samr.pipe_type == SAM_PIPE_DOM)
796 DEBUG(0, ("No domain sam handle was created!\n"));
800 if (!(conn = (struct winbindd_cm_conn *)
801 malloc(sizeof(struct winbindd_cm_conn))))
806 fstrcpy(conn->domain, basic_conn->domain);
807 fstrcpy(conn->controller, basic_conn->controller);
808 fstrcpy(conn->pipe_name, basic_conn->pipe_name);
810 conn->pipe_data.samr.pipe_type = SAM_PIPE_USER;
811 conn->cli = basic_conn->cli;
812 conn->pipe_data.samr.rid = user_rid;
814 result = cli_samr_open_user(conn->cli, conn->cli->mem_ctx,
815 &basic_conn->pol, des_access, user_rid,
818 if (!NT_STATUS_IS_OK(result))
823 DLIST_ADD(cm_conns, conn);
832 /* Return a SAM policy handle on a domain group */
834 CLI_POLICY_HND *cm_get_sam_group_handle(char *domain, DOM_SID *domain_sid,
837 struct winbindd_cm_conn *conn, *basic_conn = NULL;
838 static CLI_POLICY_HND hnd;
840 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
842 /* Look for existing connections */
844 for (conn = cm_conns; conn; conn = conn->next) {
845 if (strequal(conn->domain, domain) &&
846 strequal(conn->pipe_name, PIPE_SAMR) &&
847 conn->pipe_data.samr.pipe_type == SAM_PIPE_GROUP &&
848 conn->pipe_data.samr.rid == group_rid) {
850 if (!connection_ok(conn)) {
851 /* Shutdown cli? Free conn? Allow retry of DC? */
852 DLIST_REMOVE(cm_conns, conn);
860 /* Create a domain handle to open a user handle from */
862 if (!cm_get_sam_dom_handle(domain, domain_sid))
865 for (conn = cm_conns; conn; conn = conn->next) {
866 if (strequal(conn->domain, domain) &&
867 strequal(conn->pipe_name, PIPE_SAMR) &&
868 conn->pipe_data.samr.pipe_type == SAM_PIPE_DOM)
873 DEBUG(0, ("No domain sam handle was created!\n"));
877 if (!(conn = (struct winbindd_cm_conn *)
878 malloc(sizeof(struct winbindd_cm_conn))))
883 fstrcpy(conn->domain, basic_conn->domain);
884 fstrcpy(conn->controller, basic_conn->controller);
885 fstrcpy(conn->pipe_name, basic_conn->pipe_name);
887 conn->pipe_data.samr.pipe_type = SAM_PIPE_GROUP;
888 conn->cli = basic_conn->cli;
889 conn->pipe_data.samr.rid = group_rid;
891 result = cli_samr_open_group(conn->cli, conn->cli->mem_ctx,
892 &basic_conn->pol, des_access, group_rid,
895 if (!NT_STATUS_IS_OK(result))
900 DLIST_ADD(cm_conns, conn);
911 /* Get a handle on a netlogon pipe. This is a bit of a hack to re-use the
912 netlogon pipe as no handle is returned. */
914 NTSTATUS cm_get_netlogon_cli(const char *domain, const unsigned char *trust_passwd,
915 struct cli_state **cli)
917 NTSTATUS result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
918 struct winbindd_cm_conn *conn;
919 uint32 neg_flags = 0x000001ff;
922 return NT_STATUS_INVALID_PARAMETER;
925 /* Open an initial conection */
927 if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_NETLOGON, &conn))) {
931 result = cli_nt_setup_creds(conn->cli, get_sec_chan(), trust_passwd, &neg_flags, 2);
933 if (!NT_STATUS_IS_OK(result)) {
934 DEBUG(0, ("error connecting to domain password server: %s\n",
937 /* Hit the cache code again. This cleans out the old connection and gets a new one */
938 if (conn->cli->fd == -1) {
939 if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_NETLOGON, &conn))) {
944 result = cli_nt_setup_creds( conn->cli, get_sec_chan(),trust_passwd, &neg_flags, 2);
947 if (!NT_STATUS_IS_OK(result)) {
948 cli_shutdown(conn->cli);
949 DLIST_REMOVE(cm_conns, conn);
960 /* Dump the current connection status */
962 static void dump_conn_list(void)
964 struct winbindd_cm_conn *con;
966 DEBUG(0, ("\tDomain Controller Pipe\n"));
968 for(con = cm_conns; con; con = con->next) {
971 /* Display pipe info */
973 if (asprintf(&msg, "\t%-15s %-15s %-16s", con->domain, con->controller, con->pipe_name) < 0) {
974 DEBUG(0, ("Error: not enough memory!\n"));
976 DEBUG(0, ("%s\n", msg));
982 void winbindd_cm_status(void)
984 /* List open connections */
986 DEBUG(0, ("winbindd connection manager status:\n"));
991 DEBUG(0, ("\tNo active connections\n"));