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
)));
140 static BOOL
cm_get_dc_name(const char *domain
, fstring srv_name
, struct in_addr
*ip_out
)
142 static struct get_dc_name_cache
*get_dc_name_cache
;
143 struct get_dc_name_cache
*dcc
;
144 struct in_addr dc_ip
;
147 /* Check the cache for previous lookups */
149 for (dcc
= get_dc_name_cache
; dcc
; dcc
= dcc
->next
) {
151 if (!strequal(domain
, dcc
->domain_name
))
152 continue; /* Not our domain */
154 if ((time(NULL
) - dcc
->lookup_time
) >
155 GET_DC_NAME_CACHE_TIMEOUT
) {
157 /* Cache entry has expired, delete it */
159 DEBUG(10, ("get_dc_name_cache entry expired for %s\n", domain
));
161 DLIST_REMOVE(get_dc_name_cache
, dcc
);
167 /* Return a positive or negative lookup for this domain */
169 if (dcc
->srv_name
[0]) {
170 DEBUG(10, ("returning positive get_dc_name_cache entry for %s\n", domain
));
171 fstrcpy(srv_name
, dcc
->srv_name
);
174 DEBUG(10, ("returning negative get_dc_name_cache entry for %s\n", domain
));
179 /* Add cache entry for this lookup. */
181 DEBUG(10, ("Creating get_dc_name_cache entry for %s\n", domain
));
183 if (!(dcc
= (struct get_dc_name_cache
*)
184 malloc(sizeof(struct get_dc_name_cache
))))
189 fstrcpy(dcc
->domain_name
, domain
);
190 dcc
->lookup_time
= time(NULL
);
192 DLIST_ADD(get_dc_name_cache
, dcc
);
197 if (lp_security() == SEC_ADS
) {
198 ret
= cm_ads_find_dc(domain
, &dc_ip
, srv_name
);
201 /* fall back on rpc methods if the ADS methods fail */
202 ret
= rpc_find_dc(domain
, srv_name
, &dc_ip
);
209 /* We have a name so make the cache entry positive now */
210 fstrcpy(dcc
->srv_name
, srv_name
);
212 DEBUG(3, ("cm_get_dc_name: Returning DC %s (%s) for domain %s\n", srv_name
,
213 inet_ntoa(dc_ip
), domain
));
220 /* Choose between anonymous or authenticated connections. We need to use
221 an authenticated connection if DCs have the RestrictAnonymous registry
222 entry set > 0, or the "Additional restrictions for anonymous
223 connections" set in the win2k Local Security Policy.
225 Caller to free() result in domain, username, password
228 static void cm_get_ipc_userpass(char **username
, char **domain
, char **password
)
230 *username
= secrets_fetch(SECRETS_AUTH_USER
, NULL
);
231 *domain
= secrets_fetch(SECRETS_AUTH_DOMAIN
, NULL
);
232 *password
= secrets_fetch(SECRETS_AUTH_PASSWORD
, NULL
);
234 if (*username
&& **username
) {
236 if (!*domain
|| !**domain
)
237 *domain
= smb_xstrdup(lp_workgroup());
239 if (!*password
|| !**password
)
240 *password
= smb_xstrdup("");
242 DEBUG(3, ("IPC$ connections done by user %s\\%s\n",
243 *domain
, *username
));
246 DEBUG(3, ("IPC$ connections done anonymously\n"));
247 *username
= smb_xstrdup("");
248 *domain
= smb_xstrdup("");
249 *password
= smb_xstrdup("");
253 /* Open a new smb pipe connection to a DC on a given domain. Cache
254 negative creation attempts so we don't try and connect to broken
255 machines too often. */
257 #define FAILED_CONNECTION_CACHE_TIMEOUT 30 /* Seconds between attempts */
259 struct failed_connection_cache
{
264 struct failed_connection_cache
*prev
, *next
;
267 static struct failed_connection_cache
*failed_connection_cache
;
269 /* Add an entry to the failed conneciton cache */
271 static void add_failed_connection_entry(struct winbindd_cm_conn
*new_conn
,
274 struct failed_connection_cache
*fcc
;
276 SMB_ASSERT(!NT_STATUS_IS_OK(result
));
278 /* Check we already aren't in the cache */
280 for (fcc
= failed_connection_cache
; fcc
; fcc
= fcc
->next
) {
281 if (strequal(fcc
->domain_name
, new_conn
->domain
)) {
282 DEBUG(10, ("domain %s already tried and failed\n",
288 /* Create negative lookup cache entry for this domain and controller */
290 if (!(fcc
= (struct failed_connection_cache
*)
291 malloc(sizeof(struct failed_connection_cache
)))) {
292 DEBUG(0, ("malloc failed in add_failed_connection_entry!\n"));
298 fstrcpy(fcc
->domain_name
, new_conn
->domain
);
299 fstrcpy(fcc
->controller
, new_conn
->controller
);
300 fcc
->lookup_time
= time(NULL
);
301 fcc
->nt_status
= result
;
303 DLIST_ADD(failed_connection_cache
, fcc
);
306 /* Open a connction to the remote server, cache failures for 30 seconds */
308 static NTSTATUS
cm_open_connection(const char *domain
, const int pipe_index
,
309 struct winbindd_cm_conn
*new_conn
)
311 struct failed_connection_cache
*fcc
;
313 char *ipc_username
, *ipc_domain
, *ipc_password
;
314 struct in_addr dc_ip
;
320 fstrcpy(new_conn
->domain
, domain
);
321 fstrcpy(new_conn
->pipe_name
, get_pipe_name_from_index(pipe_index
));
323 /* Look for a domain controller for this domain. Negative results
324 are cached so don't bother applying the caching for this
325 function just yet. */
327 if (!cm_get_dc_name(domain
, new_conn
->controller
, &dc_ip
)) {
328 result
= NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND
;
329 add_failed_connection_entry(new_conn
, result
);
333 /* Return false if we have tried to look up this domain and netbios
334 name before and failed. */
336 for (fcc
= failed_connection_cache
; fcc
; fcc
= fcc
->next
) {
338 if (!(strequal(domain
, fcc
->domain_name
) &&
339 strequal(new_conn
->controller
, fcc
->controller
)))
340 continue; /* Not our domain */
342 if ((time(NULL
) - fcc
->lookup_time
) >
343 FAILED_CONNECTION_CACHE_TIMEOUT
) {
345 /* Cache entry has expired, delete it */
347 DEBUG(10, ("cm_open_connection cache entry expired for %s, %s\n", domain
, new_conn
->controller
));
349 DLIST_REMOVE(failed_connection_cache
, fcc
);
355 /* The timeout hasn't expired yet so return false */
357 DEBUG(10, ("returning negative open_connection_cache entry for %s, %s\n", domain
, new_conn
->controller
));
359 result
= fcc
->nt_status
;
360 SMB_ASSERT(!NT_STATUS_IS_OK(result
));
364 /* Initialise SMB connection */
366 cm_get_ipc_userpass(&ipc_username
, &ipc_domain
, &ipc_password
);
368 DEBUG(5, ("connecting to %s from %s with username [%s]\\[%s]\n",
369 new_conn
->controller
, global_myname(), ipc_domain
, ipc_username
));
371 for (i
= 0; retry
&& (i
< 3); i
++) {
373 if (!secrets_named_mutex(new_conn
->controller
, 10)) {
374 DEBUG(0,("cm_open_connection: mutex grab failed for %s\n", new_conn
->controller
));
378 result
= cli_full_connection(&new_conn
->cli
, global_myname(), new_conn
->controller
,
379 &dc_ip
, 0, "IPC$", "IPC", ipc_username
, ipc_domain
,
380 ipc_password
, 0, &retry
);
382 secrets_named_mutex_release(new_conn
->controller
);
384 if (NT_STATUS_IS_OK(result
))
388 SAFE_FREE(ipc_username
);
389 SAFE_FREE(ipc_domain
);
390 SAFE_FREE(ipc_password
);
392 if (!NT_STATUS_IS_OK(result
)) {
393 add_failed_connection_entry(new_conn
, result
);
397 if ( !cli_nt_session_open (new_conn
->cli
, pipe_index
) ) {
398 result
= NT_STATUS_PIPE_NOT_AVAILABLE
;
400 * only cache a failure if we are not trying to open the
401 * **win2k** specific lsarpc UUID. This could be an NT PDC
402 * and therefore a failure is normal. This should probably
403 * be abstracted to a check for 2k specific pipes and wondering
404 * if the PDC is an NT4 box. but since there is only one 2k
405 * specific UUID right now, i'm not going to bother. --jerry
407 if ( !is_win2k_pipe(pipe_index
) )
408 add_failed_connection_entry(new_conn
, result
);
409 cli_shutdown(new_conn
->cli
);
416 /* Return true if a connection is still alive */
418 static BOOL
connection_ok(struct winbindd_cm_conn
*conn
)
421 smb_panic("Invalid paramater passed to conneciton_ok(): conn was NULL!\n");
426 DEBUG(0, ("Connection to %s for domain %s (pipe %s) has NULL conn->cli!\n",
427 conn
->controller
, conn
->domain
, conn
->pipe_name
));
428 smb_panic("connection_ok: conn->cli was null!");
432 if (!conn
->cli
->initialised
) {
433 DEBUG(0, ("Connection to %s for domain %s (pipe %s) was never initialised!\n",
434 conn
->controller
, conn
->domain
, conn
->pipe_name
));
435 smb_panic("connection_ok: conn->cli->initialised is False!");
439 if (conn
->cli
->fd
== -1) {
440 DEBUG(3, ("Connection to %s for domain %s (pipe %s) has died or was never started (fd == -1)\n",
441 conn
->controller
, conn
->domain
, conn
->pipe_name
));
448 /* Get a connection to the remote DC and open the pipe. If there is already a connection, use that */
450 static NTSTATUS
get_connection_from_cache(const char *domain
, const char *pipe_name
, struct winbindd_cm_conn
**conn_out
)
452 struct winbindd_cm_conn
*conn
, conn_temp
;
455 for (conn
= cm_conns
; conn
; conn
= conn
->next
) {
456 if (strequal(conn
->domain
, domain
) &&
457 strequal(conn
->pipe_name
, pipe_name
)) {
458 if (!connection_ok(conn
)) {
460 cli_shutdown(conn
->cli
);
462 ZERO_STRUCT(conn_temp
);
463 conn_temp
.next
= conn
->next
;
464 DLIST_REMOVE(cm_conns
, conn
);
466 conn
= &conn_temp
; /* Just to keep the loop moving */
474 if (!(conn
= malloc(sizeof(*conn
))))
475 return NT_STATUS_NO_MEMORY
;
479 if (!NT_STATUS_IS_OK(result
= cm_open_connection(domain
, get_pipe_index(pipe_name
), conn
))) {
480 DEBUG(3, ("Could not open a connection to %s for %s (%s)\n",
481 domain
, pipe_name
, nt_errstr(result
)));
485 DLIST_ADD(cm_conns
, conn
);
493 /**********************************************************************************
494 **********************************************************************************/
496 BOOL
cm_check_for_native_mode_win2k( const char *domain
)
499 struct winbindd_cm_conn conn
;
507 if ( !NT_STATUS_IS_OK(result
= cm_open_connection(domain
, PI_LSARPC_DS
, &conn
)) )
509 DEBUG(5, ("cm_check_for_native_mode_win2k: Could not open a connection to %s for PIPE_LSARPC (%s)\n",
510 domain
, nt_errstr(result
)));
515 if ( !NT_STATUS_IS_OK(cli_ds_getprimarydominfo( conn
.cli
,
516 conn
.cli
->mem_ctx
, DsRolePrimaryDomainInfoBasic
, &ctr
)) )
523 if ( (ctr
.basic
->flags
& DSROLE_PRIMARY_DS_RUNNING
)
524 && !(ctr
.basic
->flags
& DSROLE_PRIMARY_DS_MIXED_MODE
) )
531 cli_shutdown( conn
.cli
);
538 /* Return a LSA policy handle on a domain */
540 CLI_POLICY_HND
*cm_get_lsa_handle(const char *domain
)
542 struct winbindd_cm_conn
*conn
;
543 uint32 des_access
= SEC_RIGHTS_MAXIMUM_ALLOWED
;
545 static CLI_POLICY_HND hnd
;
547 /* Look for existing connections */
549 if (!NT_STATUS_IS_OK(result
= get_connection_from_cache(domain
, PIPE_LSARPC
, &conn
))) {
553 /* This *shitty* code needs scrapping ! JRA */
554 if (policy_handle_is_valid(&conn
->pol
)) {
560 result
= cli_lsa_open_policy(conn
->cli
, conn
->cli
->mem_ctx
, False
,
561 des_access
, &conn
->pol
);
563 if (!NT_STATUS_IS_OK(result
)) {
564 /* Hit the cache code again. This cleans out the old connection and gets a new one */
565 if (conn
->cli
->fd
== -1) { /* Try again, if the remote host disapeared */
566 if (!NT_STATUS_IS_OK(result
= get_connection_from_cache(domain
, PIPE_LSARPC
, &conn
))) {
570 result
= cli_lsa_open_policy(conn
->cli
, conn
->cli
->mem_ctx
, False
,
571 des_access
, &conn
->pol
);
574 if (!NT_STATUS_IS_OK(result
)) {
575 cli_shutdown(conn
->cli
);
576 DLIST_REMOVE(cm_conns
, conn
);
588 /* Return a SAM policy handle on a domain */
590 CLI_POLICY_HND
*cm_get_sam_handle(char *domain
)
592 struct winbindd_cm_conn
*conn
;
593 uint32 des_access
= SEC_RIGHTS_MAXIMUM_ALLOWED
;
595 static CLI_POLICY_HND hnd
;
597 /* Look for existing connections */
599 if (!NT_STATUS_IS_OK(result
= get_connection_from_cache(domain
, PIPE_SAMR
, &conn
))) {
603 /* This *shitty* code needs scrapping ! JRA */
604 if (policy_handle_is_valid(&conn
->pol
)) {
609 result
= cli_samr_connect(conn
->cli
, conn
->cli
->mem_ctx
,
610 des_access
, &conn
->pol
);
612 if (!NT_STATUS_IS_OK(result
)) {
613 /* Hit the cache code again. This cleans out the old connection and gets a new one */
614 if (conn
->cli
->fd
== -1) { /* Try again, if the remote host disapeared */
615 if (!NT_STATUS_IS_OK(result
= get_connection_from_cache(domain
, PIPE_SAMR
, &conn
))) {
619 result
= cli_samr_connect(conn
->cli
, conn
->cli
->mem_ctx
,
620 des_access
, &conn
->pol
);
623 if (!NT_STATUS_IS_OK(result
)) {
624 cli_shutdown(conn
->cli
);
625 DLIST_REMOVE(cm_conns
, conn
);
637 #if 0 /* This code now *well* out of date */
639 /* Return a SAM domain policy handle on a domain */
641 CLI_POLICY_HND
*cm_get_sam_dom_handle(char *domain
, DOM_SID
*domain_sid
)
643 struct winbindd_cm_conn
*conn
, *basic_conn
= NULL
;
644 static CLI_POLICY_HND hnd
;
646 uint32 des_access
= SEC_RIGHTS_MAXIMUM_ALLOWED
;
648 /* Look for existing connections */
650 for (conn
= cm_conns
; conn
; conn
= conn
->next
) {
651 if (strequal(conn
->domain
, domain
) &&
652 strequal(conn
->pipe_name
, PIPE_SAMR
) &&
653 conn
->pipe_data
.samr
.pipe_type
== SAM_PIPE_DOM
) {
655 if (!connection_ok(conn
)) {
656 /* Shutdown cli? Free conn? Allow retry of DC? */
657 DLIST_REMOVE(cm_conns
, conn
);
665 /* Create a basic handle to open a domain handle from */
667 if (!cm_get_sam_handle(domain
))
670 for (conn
= cm_conns
; conn
; conn
= conn
->next
) {
671 if (strequal(conn
->domain
, domain
) &&
672 strequal(conn
->pipe_name
, PIPE_SAMR
) &&
673 conn
->pipe_data
.samr
.pipe_type
== SAM_PIPE_BASIC
)
677 if (!(conn
= (struct winbindd_cm_conn
*)
678 malloc(sizeof(struct winbindd_cm_conn
))))
683 fstrcpy(conn
->domain
, basic_conn
->domain
);
684 fstrcpy(conn
->controller
, basic_conn
->controller
);
685 fstrcpy(conn
->pipe_name
, basic_conn
->pipe_name
);
687 conn
->pipe_data
.samr
.pipe_type
= SAM_PIPE_DOM
;
688 conn
->cli
= basic_conn
->cli
;
690 result
= cli_samr_open_domain(conn
->cli
, conn
->cli
->mem_ctx
,
691 &basic_conn
->pol
, des_access
,
692 domain_sid
, &conn
->pol
);
694 if (!NT_STATUS_IS_OK(result
))
699 DLIST_ADD(cm_conns
, conn
);
708 /* Return a SAM policy handle on a domain user */
710 CLI_POLICY_HND
*cm_get_sam_user_handle(char *domain
, DOM_SID
*domain_sid
,
713 struct winbindd_cm_conn
*conn
, *basic_conn
= NULL
;
714 static CLI_POLICY_HND hnd
;
716 uint32 des_access
= SEC_RIGHTS_MAXIMUM_ALLOWED
;
718 /* Look for existing connections */
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_USER
&&
724 conn
->pipe_data
.samr
.rid
== user_rid
) {
726 if (!connection_ok(conn
)) {
727 /* Shutdown cli? Free conn? Allow retry of DC? */
728 DLIST_REMOVE(cm_conns
, conn
);
736 /* Create a domain handle to open a user handle from */
738 if (!cm_get_sam_dom_handle(domain
, domain_sid
))
741 for (conn
= cm_conns
; conn
; conn
= conn
->next
) {
742 if (strequal(conn
->domain
, domain
) &&
743 strequal(conn
->pipe_name
, PIPE_SAMR
) &&
744 conn
->pipe_data
.samr
.pipe_type
== SAM_PIPE_DOM
)
749 DEBUG(0, ("No domain sam handle was created!\n"));
753 if (!(conn
= (struct winbindd_cm_conn
*)
754 malloc(sizeof(struct winbindd_cm_conn
))))
759 fstrcpy(conn
->domain
, basic_conn
->domain
);
760 fstrcpy(conn
->controller
, basic_conn
->controller
);
761 fstrcpy(conn
->pipe_name
, basic_conn
->pipe_name
);
763 conn
->pipe_data
.samr
.pipe_type
= SAM_PIPE_USER
;
764 conn
->cli
= basic_conn
->cli
;
765 conn
->pipe_data
.samr
.rid
= user_rid
;
767 result
= cli_samr_open_user(conn
->cli
, conn
->cli
->mem_ctx
,
768 &basic_conn
->pol
, des_access
, user_rid
,
771 if (!NT_STATUS_IS_OK(result
))
776 DLIST_ADD(cm_conns
, conn
);
785 /* Return a SAM policy handle on a domain group */
787 CLI_POLICY_HND
*cm_get_sam_group_handle(char *domain
, DOM_SID
*domain_sid
,
790 struct winbindd_cm_conn
*conn
, *basic_conn
= NULL
;
791 static CLI_POLICY_HND hnd
;
793 uint32 des_access
= SEC_RIGHTS_MAXIMUM_ALLOWED
;
795 /* Look for existing connections */
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_GROUP
&&
801 conn
->pipe_data
.samr
.rid
== group_rid
) {
803 if (!connection_ok(conn
)) {
804 /* Shutdown cli? Free conn? Allow retry of DC? */
805 DLIST_REMOVE(cm_conns
, conn
);
813 /* Create a domain handle to open a user handle from */
815 if (!cm_get_sam_dom_handle(domain
, domain_sid
))
818 for (conn
= cm_conns
; conn
; conn
= conn
->next
) {
819 if (strequal(conn
->domain
, domain
) &&
820 strequal(conn
->pipe_name
, PIPE_SAMR
) &&
821 conn
->pipe_data
.samr
.pipe_type
== SAM_PIPE_DOM
)
826 DEBUG(0, ("No domain sam handle was created!\n"));
830 if (!(conn
= (struct winbindd_cm_conn
*)
831 malloc(sizeof(struct winbindd_cm_conn
))))
836 fstrcpy(conn
->domain
, basic_conn
->domain
);
837 fstrcpy(conn
->controller
, basic_conn
->controller
);
838 fstrcpy(conn
->pipe_name
, basic_conn
->pipe_name
);
840 conn
->pipe_data
.samr
.pipe_type
= SAM_PIPE_GROUP
;
841 conn
->cli
= basic_conn
->cli
;
842 conn
->pipe_data
.samr
.rid
= group_rid
;
844 result
= cli_samr_open_group(conn
->cli
, conn
->cli
->mem_ctx
,
845 &basic_conn
->pol
, des_access
, group_rid
,
848 if (!NT_STATUS_IS_OK(result
))
853 DLIST_ADD(cm_conns
, conn
);
864 /* Get a handle on a netlogon pipe. This is a bit of a hack to re-use the
865 netlogon pipe as no handle is returned. */
867 NTSTATUS
cm_get_netlogon_cli(const char *domain
, const unsigned char *trust_passwd
,
868 struct cli_state
**cli
)
870 NTSTATUS result
= NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND
;
871 struct winbindd_cm_conn
*conn
;
872 uint32 neg_flags
= 0x000001ff;
875 return NT_STATUS_INVALID_PARAMETER
;
878 /* Open an initial conection */
880 if (!NT_STATUS_IS_OK(result
= get_connection_from_cache(domain
, PIPE_NETLOGON
, &conn
))) {
884 result
= cli_nt_setup_creds(conn
->cli
, get_sec_chan(), trust_passwd
, &neg_flags
, 2);
886 if (!NT_STATUS_IS_OK(result
)) {
887 DEBUG(0, ("error connecting to domain password server: %s\n",
890 /* Hit the cache code again. This cleans out the old connection and gets a new one */
891 if (conn
->cli
->fd
== -1) {
892 if (!NT_STATUS_IS_OK(result
= get_connection_from_cache(domain
, PIPE_NETLOGON
, &conn
))) {
897 result
= cli_nt_setup_creds( conn
->cli
, get_sec_chan(),trust_passwd
, &neg_flags
, 2);
900 if (!NT_STATUS_IS_OK(result
)) {
901 cli_shutdown(conn
->cli
);
902 DLIST_REMOVE(cm_conns
, conn
);
913 /* Dump the current connection status */
915 static void dump_conn_list(void)
917 struct winbindd_cm_conn
*con
;
919 DEBUG(0, ("\tDomain Controller Pipe\n"));
921 for(con
= cm_conns
; con
; con
= con
->next
) {
924 /* Display pipe info */
926 if (asprintf(&msg
, "\t%-15s %-15s %-16s", con
->domain
, con
->controller
, con
->pipe_name
) < 0) {
927 DEBUG(0, ("Error: not enough memory!\n"));
929 DEBUG(0, ("%s\n", msg
));
935 void winbindd_cm_status(void)
937 /* List open connections */
939 DEBUG(0, ("winbindd connection manager status:\n"));
944 DEBUG(0, ("\tNo active connections\n"));