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;
147 if (!get_dc_list(domain, &ip_list, &count, &list_ordered)) {
148 struct in_addr pdc_ip;
150 if (!get_pdc_ip(domain, &pdc_ip)) {
151 DEBUG(3, ("Could not look up any DCs for domain %s\n",
156 ip_list = (struct in_addr *)malloc(sizeof(struct in_addr));
165 /* Pick a nice close server, but only if the list was not ordered */
166 if (!list_ordered && (count > 1) ) {
167 qsort(ip_list, count, sizeof(struct in_addr), QSORT_CAST ip_compare);
170 for (i = 0; i < count; i++) {
171 if (is_zero_ip(ip_list[i]))
174 if (name_status_find(domain, 0x1c, 0x20, ip_list[i], srv_name)) {
188 static BOOL cm_get_dc_name(const char *domain, fstring srv_name, struct in_addr *ip_out)
190 static struct get_dc_name_cache *get_dc_name_cache;
191 struct get_dc_name_cache *dcc;
192 struct in_addr dc_ip;
195 /* Check the cache for previous lookups */
197 for (dcc = get_dc_name_cache; dcc; dcc = dcc->next) {
199 if (!strequal(domain, dcc->domain_name))
200 continue; /* Not our domain */
202 if ((time(NULL) - dcc->lookup_time) >
203 GET_DC_NAME_CACHE_TIMEOUT) {
205 /* Cache entry has expired, delete it */
207 DEBUG(10, ("get_dc_name_cache entry expired for %s\n", domain));
209 DLIST_REMOVE(get_dc_name_cache, dcc);
215 /* Return a positive or negative lookup for this domain */
217 if (dcc->srv_name[0]) {
218 DEBUG(10, ("returning positive get_dc_name_cache entry for %s\n", domain));
219 fstrcpy(srv_name, dcc->srv_name);
222 DEBUG(10, ("returning negative get_dc_name_cache entry for %s\n", domain));
227 /* Add cache entry for this lookup. */
229 DEBUG(10, ("Creating get_dc_name_cache entry for %s\n", domain));
231 if (!(dcc = (struct get_dc_name_cache *)
232 malloc(sizeof(struct get_dc_name_cache))))
237 fstrcpy(dcc->domain_name, domain);
238 dcc->lookup_time = time(NULL);
240 DLIST_ADD(get_dc_name_cache, dcc);
245 if (lp_security() == SEC_ADS) {
246 ret = cm_ads_find_dc(domain, &dc_ip, srv_name);
249 /* fall back on rpc methods if the ADS methods fail */
250 ret = cm_rpc_find_dc(domain, &dc_ip, srv_name);
257 /* We have a name so make the cache entry positive now */
258 fstrcpy(dcc->srv_name, srv_name);
260 DEBUG(3, ("cm_get_dc_name: Returning DC %s (%s) for domain %s\n", srv_name,
261 inet_ntoa(dc_ip), domain));
268 /* Choose between anonymous or authenticated connections. We need to use
269 an authenticated connection if DCs have the RestrictAnonymous registry
270 entry set > 0, or the "Additional restrictions for anonymous
271 connections" set in the win2k Local Security Policy.
273 Caller to free() result in domain, username, password
276 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
278 *username = secrets_fetch(SECRETS_AUTH_USER, NULL);
279 *domain = secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
280 *password = secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
282 if (*username && **username) {
284 if (!*domain || !**domain)
285 *domain = smb_xstrdup(lp_workgroup());
287 if (!*password || !**password)
288 *password = smb_xstrdup("");
290 DEBUG(3, ("IPC$ connections done by user %s\\%s\n",
291 *domain, *username));
294 DEBUG(3, ("IPC$ connections done anonymously\n"));
295 *username = smb_xstrdup("");
296 *domain = smb_xstrdup("");
297 *password = smb_xstrdup("");
301 /* Open a new smb pipe connection to a DC on a given domain. Cache
302 negative creation attempts so we don't try and connect to broken
303 machines too often. */
305 #define FAILED_CONNECTION_CACHE_TIMEOUT 30 /* Seconds between attempts */
307 struct failed_connection_cache {
312 struct failed_connection_cache *prev, *next;
315 static struct failed_connection_cache *failed_connection_cache;
317 /* Add an entry to the failed conneciton cache */
319 static void add_failed_connection_entry(struct winbindd_cm_conn *new_conn,
322 struct failed_connection_cache *fcc;
324 SMB_ASSERT(!NT_STATUS_IS_OK(result));
326 /* Check we already aren't in the cache */
328 for (fcc = failed_connection_cache; fcc; fcc = fcc->next) {
329 if (strequal(fcc->domain_name, new_conn->domain)) {
330 DEBUG(10, ("domain %s already tried and failed\n",
336 /* Create negative lookup cache entry for this domain and controller */
338 if (!(fcc = (struct failed_connection_cache *)
339 malloc(sizeof(struct failed_connection_cache)))) {
340 DEBUG(0, ("malloc failed in add_failed_connection_entry!\n"));
346 fstrcpy(fcc->domain_name, new_conn->domain);
347 fstrcpy(fcc->controller, new_conn->controller);
348 fcc->lookup_time = time(NULL);
349 fcc->nt_status = result;
351 DLIST_ADD(failed_connection_cache, fcc);
354 /* Open a connction to the remote server, cache failures for 30 seconds */
356 static NTSTATUS cm_open_connection(const char *domain, const int pipe_index,
357 struct winbindd_cm_conn *new_conn)
359 struct failed_connection_cache *fcc;
361 char *ipc_username, *ipc_domain, *ipc_password;
362 struct in_addr dc_ip;
368 fstrcpy(new_conn->domain, domain);
369 fstrcpy(new_conn->pipe_name, get_pipe_name_from_index(pipe_index));
371 /* Look for a domain controller for this domain. Negative results
372 are cached so don't bother applying the caching for this
373 function just yet. */
375 if (!cm_get_dc_name(domain, new_conn->controller, &dc_ip)) {
376 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
377 add_failed_connection_entry(new_conn, result);
381 /* Return false if we have tried to look up this domain and netbios
382 name before and failed. */
384 for (fcc = failed_connection_cache; fcc; fcc = fcc->next) {
386 if (!(strequal(domain, fcc->domain_name) &&
387 strequal(new_conn->controller, fcc->controller)))
388 continue; /* Not our domain */
390 if ((time(NULL) - fcc->lookup_time) >
391 FAILED_CONNECTION_CACHE_TIMEOUT) {
393 /* Cache entry has expired, delete it */
395 DEBUG(10, ("cm_open_connection cache entry expired for %s, %s\n", domain, new_conn->controller));
397 DLIST_REMOVE(failed_connection_cache, fcc);
403 /* The timeout hasn't expired yet so return false */
405 DEBUG(10, ("returning negative open_connection_cache entry for %s, %s\n", domain, new_conn->controller));
407 result = fcc->nt_status;
408 SMB_ASSERT(!NT_STATUS_IS_OK(result));
412 /* Initialise SMB connection */
414 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
416 DEBUG(5, ("connecting to %s from %s with username [%s]\\[%s]\n",
417 new_conn->controller, global_myname(), ipc_domain, ipc_username));
419 for (i = 0; retry && (i < 3); i++) {
421 if (!secrets_named_mutex(new_conn->controller, 10)) {
422 DEBUG(0,("cm_open_connection: mutex grab failed for %s\n", new_conn->controller));
426 result = cli_full_connection(&new_conn->cli, global_myname(), new_conn->controller,
427 &dc_ip, 0, "IPC$", "IPC", ipc_username, ipc_domain,
428 ipc_password, 0, &retry);
430 secrets_named_mutex_release(new_conn->controller);
432 if (NT_STATUS_IS_OK(result))
436 SAFE_FREE(ipc_username);
437 SAFE_FREE(ipc_domain);
438 SAFE_FREE(ipc_password);
440 if (!NT_STATUS_IS_OK(result)) {
441 add_failed_connection_entry(new_conn, result);
445 if ( !cli_nt_session_open (new_conn->cli, pipe_index) ) {
446 result = NT_STATUS_PIPE_NOT_AVAILABLE;
448 * only cache a failure if we are not trying to open the
449 * **win2k** specific lsarpc UUID. This could be an NT PDC
450 * and therefore a failure is normal. This should probably
451 * be abstracted to a check for 2k specific pipes and wondering
452 * if the PDC is an NT4 box. but since there is only one 2k
453 * specific UUID right now, i'm not going to bother. --jerry
455 if ( !is_win2k_pipe(pipe_index) )
456 add_failed_connection_entry(new_conn, result);
457 cli_shutdown(new_conn->cli);
464 /* Return true if a connection is still alive */
466 static BOOL connection_ok(struct winbindd_cm_conn *conn)
469 smb_panic("Invalid paramater passed to conneciton_ok(): conn was NULL!\n");
474 DEBUG(0, ("Connection to %s for domain %s (pipe %s) has NULL conn->cli!\n",
475 conn->controller, conn->domain, conn->pipe_name));
476 smb_panic("connection_ok: conn->cli was null!");
480 if (!conn->cli->initialised) {
481 DEBUG(0, ("Connection to %s for domain %s (pipe %s) was never initialised!\n",
482 conn->controller, conn->domain, conn->pipe_name));
483 smb_panic("connection_ok: conn->cli->initialised is False!");
487 if (conn->cli->fd == -1) {
488 DEBUG(3, ("Connection to %s for domain %s (pipe %s) has died or was never started (fd == -1)\n",
489 conn->controller, conn->domain, conn->pipe_name));
496 /* Get a connection to the remote DC and open the pipe. If there is already a connection, use that */
498 static NTSTATUS get_connection_from_cache(const char *domain, const char *pipe_name, struct winbindd_cm_conn **conn_out)
500 struct winbindd_cm_conn *conn, conn_temp;
503 for (conn = cm_conns; conn; conn = conn->next) {
504 if (strequal(conn->domain, domain) &&
505 strequal(conn->pipe_name, pipe_name)) {
506 if (!connection_ok(conn)) {
508 cli_shutdown(conn->cli);
510 ZERO_STRUCT(conn_temp);
511 conn_temp.next = conn->next;
512 DLIST_REMOVE(cm_conns, conn);
514 conn = &conn_temp; /* Just to keep the loop moving */
522 if (!(conn = malloc(sizeof(*conn))))
523 return NT_STATUS_NO_MEMORY;
527 if (!NT_STATUS_IS_OK(result = cm_open_connection(domain, get_pipe_index(pipe_name), conn))) {
528 DEBUG(3, ("Could not open a connection to %s for %s (%s)\n",
529 domain, pipe_name, nt_errstr(result)));
533 DLIST_ADD(cm_conns, conn);
541 /**********************************************************************************
542 **********************************************************************************/
544 BOOL cm_check_for_native_mode_win2k( const char *domain )
547 struct winbindd_cm_conn conn;
555 if ( !NT_STATUS_IS_OK(result = cm_open_connection(domain, PI_LSARPC_DS, &conn)) )
557 DEBUG(5, ("cm_check_for_native_mode_win2k: Could not open a connection to %s for PIPE_LSARPC (%s)\n",
558 domain, nt_errstr(result)));
563 if ( !NT_STATUS_IS_OK(cli_ds_getprimarydominfo( conn.cli,
564 conn.cli->mem_ctx, DsRolePrimaryDomainInfoBasic, &ctr)) )
571 if ( (ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING)
572 && !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE) )
579 cli_shutdown( conn.cli );
586 /* Return a LSA policy handle on a domain */
588 CLI_POLICY_HND *cm_get_lsa_handle(const char *domain)
590 struct winbindd_cm_conn *conn;
591 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
593 static CLI_POLICY_HND hnd;
595 /* Look for existing connections */
597 if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_LSARPC, &conn))) {
601 /* This *shitty* code needs scrapping ! JRA */
602 if (policy_handle_is_valid(&conn->pol)) {
608 result = cli_lsa_open_policy(conn->cli, conn->cli->mem_ctx, False,
609 des_access, &conn->pol);
611 if (!NT_STATUS_IS_OK(result)) {
612 /* Hit the cache code again. This cleans out the old connection and gets a new one */
613 if (conn->cli->fd == -1) { /* Try again, if the remote host disapeared */
614 if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_LSARPC, &conn))) {
618 result = cli_lsa_open_policy(conn->cli, conn->cli->mem_ctx, False,
619 des_access, &conn->pol);
622 if (!NT_STATUS_IS_OK(result)) {
623 cli_shutdown(conn->cli);
624 DLIST_REMOVE(cm_conns, conn);
636 /* Return a SAM policy handle on a domain */
638 CLI_POLICY_HND *cm_get_sam_handle(char *domain)
640 struct winbindd_cm_conn *conn;
641 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
643 static CLI_POLICY_HND hnd;
645 /* Look for existing connections */
647 if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_SAMR, &conn))) {
651 /* This *shitty* code needs scrapping ! JRA */
652 if (policy_handle_is_valid(&conn->pol)) {
657 result = cli_samr_connect(conn->cli, conn->cli->mem_ctx,
658 des_access, &conn->pol);
660 if (!NT_STATUS_IS_OK(result)) {
661 /* Hit the cache code again. This cleans out the old connection and gets a new one */
662 if (conn->cli->fd == -1) { /* Try again, if the remote host disapeared */
663 if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_SAMR, &conn))) {
667 result = cli_samr_connect(conn->cli, conn->cli->mem_ctx,
668 des_access, &conn->pol);
671 if (!NT_STATUS_IS_OK(result)) {
672 cli_shutdown(conn->cli);
673 DLIST_REMOVE(cm_conns, conn);
685 #if 0 /* This code now *well* out of date */
687 /* Return a SAM domain policy handle on a domain */
689 CLI_POLICY_HND *cm_get_sam_dom_handle(char *domain, DOM_SID *domain_sid)
691 struct winbindd_cm_conn *conn, *basic_conn = NULL;
692 static CLI_POLICY_HND hnd;
694 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
696 /* Look for existing connections */
698 for (conn = cm_conns; conn; conn = conn->next) {
699 if (strequal(conn->domain, domain) &&
700 strequal(conn->pipe_name, PIPE_SAMR) &&
701 conn->pipe_data.samr.pipe_type == SAM_PIPE_DOM) {
703 if (!connection_ok(conn)) {
704 /* Shutdown cli? Free conn? Allow retry of DC? */
705 DLIST_REMOVE(cm_conns, conn);
713 /* Create a basic handle to open a domain handle from */
715 if (!cm_get_sam_handle(domain))
718 for (conn = cm_conns; conn; conn = conn->next) {
719 if (strequal(conn->domain, domain) &&
720 strequal(conn->pipe_name, PIPE_SAMR) &&
721 conn->pipe_data.samr.pipe_type == SAM_PIPE_BASIC)
725 if (!(conn = (struct winbindd_cm_conn *)
726 malloc(sizeof(struct winbindd_cm_conn))))
731 fstrcpy(conn->domain, basic_conn->domain);
732 fstrcpy(conn->controller, basic_conn->controller);
733 fstrcpy(conn->pipe_name, basic_conn->pipe_name);
735 conn->pipe_data.samr.pipe_type = SAM_PIPE_DOM;
736 conn->cli = basic_conn->cli;
738 result = cli_samr_open_domain(conn->cli, conn->cli->mem_ctx,
739 &basic_conn->pol, des_access,
740 domain_sid, &conn->pol);
742 if (!NT_STATUS_IS_OK(result))
747 DLIST_ADD(cm_conns, conn);
756 /* Return a SAM policy handle on a domain user */
758 CLI_POLICY_HND *cm_get_sam_user_handle(char *domain, DOM_SID *domain_sid,
761 struct winbindd_cm_conn *conn, *basic_conn = NULL;
762 static CLI_POLICY_HND hnd;
764 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
766 /* Look for existing connections */
768 for (conn = cm_conns; conn; conn = conn->next) {
769 if (strequal(conn->domain, domain) &&
770 strequal(conn->pipe_name, PIPE_SAMR) &&
771 conn->pipe_data.samr.pipe_type == SAM_PIPE_USER &&
772 conn->pipe_data.samr.rid == user_rid) {
774 if (!connection_ok(conn)) {
775 /* Shutdown cli? Free conn? Allow retry of DC? */
776 DLIST_REMOVE(cm_conns, conn);
784 /* Create a domain handle to open a user handle from */
786 if (!cm_get_sam_dom_handle(domain, domain_sid))
789 for (conn = cm_conns; conn; conn = conn->next) {
790 if (strequal(conn->domain, domain) &&
791 strequal(conn->pipe_name, PIPE_SAMR) &&
792 conn->pipe_data.samr.pipe_type == SAM_PIPE_DOM)
797 DEBUG(0, ("No domain sam handle was created!\n"));
801 if (!(conn = (struct winbindd_cm_conn *)
802 malloc(sizeof(struct winbindd_cm_conn))))
807 fstrcpy(conn->domain, basic_conn->domain);
808 fstrcpy(conn->controller, basic_conn->controller);
809 fstrcpy(conn->pipe_name, basic_conn->pipe_name);
811 conn->pipe_data.samr.pipe_type = SAM_PIPE_USER;
812 conn->cli = basic_conn->cli;
813 conn->pipe_data.samr.rid = user_rid;
815 result = cli_samr_open_user(conn->cli, conn->cli->mem_ctx,
816 &basic_conn->pol, des_access, user_rid,
819 if (!NT_STATUS_IS_OK(result))
824 DLIST_ADD(cm_conns, conn);
833 /* Return a SAM policy handle on a domain group */
835 CLI_POLICY_HND *cm_get_sam_group_handle(char *domain, DOM_SID *domain_sid,
838 struct winbindd_cm_conn *conn, *basic_conn = NULL;
839 static CLI_POLICY_HND hnd;
841 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
843 /* Look for existing connections */
845 for (conn = cm_conns; conn; conn = conn->next) {
846 if (strequal(conn->domain, domain) &&
847 strequal(conn->pipe_name, PIPE_SAMR) &&
848 conn->pipe_data.samr.pipe_type == SAM_PIPE_GROUP &&
849 conn->pipe_data.samr.rid == group_rid) {
851 if (!connection_ok(conn)) {
852 /* Shutdown cli? Free conn? Allow retry of DC? */
853 DLIST_REMOVE(cm_conns, conn);
861 /* Create a domain handle to open a user handle from */
863 if (!cm_get_sam_dom_handle(domain, domain_sid))
866 for (conn = cm_conns; conn; conn = conn->next) {
867 if (strequal(conn->domain, domain) &&
868 strequal(conn->pipe_name, PIPE_SAMR) &&
869 conn->pipe_data.samr.pipe_type == SAM_PIPE_DOM)
874 DEBUG(0, ("No domain sam handle was created!\n"));
878 if (!(conn = (struct winbindd_cm_conn *)
879 malloc(sizeof(struct winbindd_cm_conn))))
884 fstrcpy(conn->domain, basic_conn->domain);
885 fstrcpy(conn->controller, basic_conn->controller);
886 fstrcpy(conn->pipe_name, basic_conn->pipe_name);
888 conn->pipe_data.samr.pipe_type = SAM_PIPE_GROUP;
889 conn->cli = basic_conn->cli;
890 conn->pipe_data.samr.rid = group_rid;
892 result = cli_samr_open_group(conn->cli, conn->cli->mem_ctx,
893 &basic_conn->pol, des_access, group_rid,
896 if (!NT_STATUS_IS_OK(result))
901 DLIST_ADD(cm_conns, conn);
912 /* Get a handle on a netlogon pipe. This is a bit of a hack to re-use the
913 netlogon pipe as no handle is returned. */
915 NTSTATUS cm_get_netlogon_cli(const char *domain, const unsigned char *trust_passwd,
916 struct cli_state **cli)
918 NTSTATUS result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
919 struct winbindd_cm_conn *conn;
920 uint32 neg_flags = 0x000001ff;
923 return NT_STATUS_INVALID_PARAMETER;
926 /* Open an initial conection */
928 if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_NETLOGON, &conn))) {
932 result = cli_nt_setup_creds(conn->cli, get_sec_chan(), trust_passwd, &neg_flags, 2);
934 if (!NT_STATUS_IS_OK(result)) {
935 DEBUG(0, ("error connecting to domain password server: %s\n",
938 /* Hit the cache code again. This cleans out the old connection and gets a new one */
939 if (conn->cli->fd == -1) {
940 if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_NETLOGON, &conn))) {
945 result = cli_nt_setup_creds( conn->cli, get_sec_chan(),trust_passwd, &neg_flags, 2);
948 if (!NT_STATUS_IS_OK(result)) {
949 cli_shutdown(conn->cli);
950 DLIST_REMOVE(cm_conns, conn);
961 /* Dump the current connection status */
963 static void dump_conn_list(void)
965 struct winbindd_cm_conn *con;
967 DEBUG(0, ("\tDomain Controller Pipe\n"));
969 for(con = cm_conns; con; con = con->next) {
972 /* Display pipe info */
974 if (asprintf(&msg, "\t%-15s %-15s %-16s", con->domain, con->controller, con->pipe_name) < 0) {
975 DEBUG(0, ("Error: not enough memory!\n"));
977 DEBUG(0, ("%s\n", msg));
983 void winbindd_cm_status(void)
985 /* List open connections */
987 DEBUG(0, ("winbindd connection manager status:\n"));
992 DEBUG(0, ("\tNo active connections\n"));