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, exclude_ip;
146 zero_ip(&exclude_ip);
148 /* Lookup domain controller name. Try the real PDC first to avoid
151 if (get_dc_list(True, domain, &ip_list, &count)) {
152 if (name_status_find(domain, 0x1c, 0x20, ip_list[0], srv_name)) {
157 /* Didn't get name, remember not to talk to this DC. */
158 exclude_ip = ip_list[0];
162 if (!get_dc_list(False, domain, &ip_list, &count)) {
163 DEBUG(3, ("Could not look up dc's for domain %s\n", domain));
167 /* Remove the entry we've already failed with (should be the PDC). */
168 for (i = 0; i < count; i++) {
169 if (ip_equal( exclude_ip, ip_list[i]))
170 zero_ip(&ip_list[i]);
173 /* Pick a nice close server */
174 /* Look for DC on local net */
175 for (i = 0; i < count; i++) {
176 if (is_zero_ip(ip_list[i]))
179 if (!is_local_net(ip_list[i]))
182 if (name_status_find(domain, 0x1c, 0x20, ip_list[i], srv_name)) {
187 zero_ip(&ip_list[i]);
191 * Secondly try and contact a random PDC/BDC.
194 i = (sys_random() % count);
196 if (!is_zero_ip(ip_list[i]) &&
197 name_status_find(domain, 0x1c, 0x20,
198 ip_list[i], srv_name)) {
203 zero_ip(&ip_list[i]); /* Tried and failed. */
205 /* Finally return first DC that we can contact using a node
207 for (i = 0; i < count; i++) {
208 if (is_zero_ip(ip_list[i]))
211 if (name_status_find(domain, 0x1c, 0x20, ip_list[i], srv_name)) {
224 static BOOL cm_get_dc_name(const char *domain, fstring srv_name, struct in_addr *ip_out)
226 static struct get_dc_name_cache *get_dc_name_cache;
227 struct get_dc_name_cache *dcc;
228 struct in_addr dc_ip;
231 /* Check the cache for previous lookups */
233 for (dcc = get_dc_name_cache; dcc; dcc = dcc->next) {
235 if (!strequal(domain, dcc->domain_name))
236 continue; /* Not our domain */
238 if ((time(NULL) - dcc->lookup_time) >
239 GET_DC_NAME_CACHE_TIMEOUT) {
241 /* Cache entry has expired, delete it */
243 DEBUG(10, ("get_dc_name_cache entry expired for %s\n", domain));
245 DLIST_REMOVE(get_dc_name_cache, dcc);
251 /* Return a positive or negative lookup for this domain */
253 if (dcc->srv_name[0]) {
254 DEBUG(10, ("returning positive get_dc_name_cache entry for %s\n", domain));
255 fstrcpy(srv_name, dcc->srv_name);
258 DEBUG(10, ("returning negative get_dc_name_cache entry for %s\n", domain));
263 /* Add cache entry for this lookup. */
265 DEBUG(10, ("Creating get_dc_name_cache entry for %s\n", domain));
267 if (!(dcc = (struct get_dc_name_cache *)
268 malloc(sizeof(struct get_dc_name_cache))))
273 fstrcpy(dcc->domain_name, domain);
274 dcc->lookup_time = time(NULL);
276 DLIST_ADD(get_dc_name_cache, dcc);
281 if (lp_security() == SEC_ADS) {
282 ret = cm_ads_find_dc(domain, &dc_ip, srv_name);
285 /* fall back on rpc methods if the ADS methods fail */
286 ret = cm_rpc_find_dc(domain, &dc_ip, srv_name);
293 /* We have a name so make the cache entry positive now */
294 fstrcpy(dcc->srv_name, srv_name);
296 DEBUG(3, ("cm_get_dc_name: Returning DC %s (%s) for domain %s\n", srv_name,
297 inet_ntoa(dc_ip), domain));
304 /* Choose between anonymous or authenticated connections. We need to use
305 an authenticated connection if DCs have the RestrictAnonymous registry
306 entry set > 0, or the "Additional restrictions for anonymous
307 connections" set in the win2k Local Security Policy.
309 Caller to free() result in domain, username, password
312 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
314 *username = secrets_fetch(SECRETS_AUTH_USER, NULL);
315 *domain = secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
316 *password = secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
318 if (*username && **username) {
319 if (!*domain || !**domain) {
320 *domain = smb_xstrdup(lp_workgroup());
323 DEBUG(3, ("IPC$ connections done by user %s\\%s\n", *domain, *username));
325 DEBUG(3, ("IPC$ connections done anonymously\n"));
326 *username = smb_xstrdup("");
327 *domain = smb_xstrdup("");
328 *password = smb_xstrdup("");
332 /* Open a new smb pipe connection to a DC on a given domain. Cache
333 negative creation attempts so we don't try and connect to broken
334 machines too often. */
336 #define FAILED_CONNECTION_CACHE_TIMEOUT 30 /* Seconds between attempts */
338 struct failed_connection_cache {
343 struct failed_connection_cache *prev, *next;
346 static struct failed_connection_cache *failed_connection_cache;
348 /* Add an entry to the failed conneciton cache */
350 static void add_failed_connection_entry(struct winbindd_cm_conn *new_conn,
353 struct failed_connection_cache *fcc;
355 SMB_ASSERT(!NT_STATUS_IS_OK(result));
357 /* Check we already aren't in the cache */
359 for (fcc = failed_connection_cache; fcc; fcc = fcc->next) {
360 if (strequal(fcc->domain_name, new_conn->domain)) {
361 DEBUG(10, ("domain %s already tried and failed\n",
367 /* Create negative lookup cache entry for this domain and controller */
369 if (!(fcc = (struct failed_connection_cache *)
370 malloc(sizeof(struct failed_connection_cache)))) {
371 DEBUG(0, ("malloc failed in add_failed_connection_entry!\n"));
377 fstrcpy(fcc->domain_name, new_conn->domain);
378 fstrcpy(fcc->controller, new_conn->controller);
379 fcc->lookup_time = time(NULL);
380 fcc->nt_status = result;
382 DLIST_ADD(failed_connection_cache, fcc);
385 /* Open a connction to the remote server, cache failures for 30 seconds */
387 static NTSTATUS cm_open_connection(const char *domain, const int pipe_index,
388 struct winbindd_cm_conn *new_conn)
390 struct failed_connection_cache *fcc;
391 extern pstring global_myname;
393 char *ipc_username, *ipc_domain, *ipc_password;
394 struct in_addr dc_ip;
400 fstrcpy(new_conn->domain, domain);
401 fstrcpy(new_conn->pipe_name, get_pipe_name_from_index(pipe_index));
403 /* Look for a domain controller for this domain. Negative results
404 are cached so don't bother applying the caching for this
405 function just yet. */
407 if (!cm_get_dc_name(domain, new_conn->controller, &dc_ip)) {
408 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
409 add_failed_connection_entry(new_conn, result);
413 /* Return false if we have tried to look up this domain and netbios
414 name before and failed. */
416 for (fcc = failed_connection_cache; fcc; fcc = fcc->next) {
418 if (!(strequal(domain, fcc->domain_name) &&
419 strequal(new_conn->controller, fcc->controller)))
420 continue; /* Not our domain */
422 if ((time(NULL) - fcc->lookup_time) >
423 FAILED_CONNECTION_CACHE_TIMEOUT) {
425 /* Cache entry has expired, delete it */
427 DEBUG(10, ("cm_open_connection cache entry expired for %s, %s\n", domain, new_conn->controller));
429 DLIST_REMOVE(failed_connection_cache, fcc);
435 /* The timeout hasn't expired yet so return false */
437 DEBUG(10, ("returning negative open_connection_cache entry for %s, %s\n", domain, new_conn->controller));
439 result = fcc->nt_status;
440 SMB_ASSERT(!NT_STATUS_IS_OK(result));
444 /* Initialise SMB connection */
446 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
448 DEBUG(5, ("connecting to %s from %s with username [%s]\\[%s]\n",
449 new_conn->controller, global_myname, ipc_domain, ipc_username));
451 for (i = 0; retry && (i < 3); i++) {
453 if (!secrets_named_mutex(new_conn->controller, 10)) {
454 DEBUG(0,("cm_open_connection: mutex grab failed for %s\n", new_conn->controller));
458 result = cli_full_connection(&(new_conn->cli), global_myname, new_conn->controller,
459 &dc_ip, 0, "IPC$", "IPC", ipc_username, ipc_domain,
460 ipc_password, 0, &retry);
462 secrets_named_mutex_release(new_conn->controller);
464 if (NT_STATUS_IS_OK(result))
468 SAFE_FREE(ipc_username);
469 SAFE_FREE(ipc_domain);
470 SAFE_FREE(ipc_password);
472 if (!NT_STATUS_IS_OK(result)) {
473 add_failed_connection_entry(new_conn, result);
477 if ( !cli_nt_session_open (new_conn->cli, pipe_index) ) {
478 result = NT_STATUS_PIPE_NOT_AVAILABLE;
480 * only cache a failure if we are not trying to open the
481 * **win2k** specific lsarpc UUID. This could be an NT PDC
482 * and therefore a failure is normal. This should probably
483 * be abstracted to a check for 2k specific pipes and wondering
484 * if the PDC is an NT4 box. but since there is only one 2k
485 * specific UUID right now, i'm not going to bother. --jerry
487 if ( !is_win2k_pipe(pipe_index) )
488 add_failed_connection_entry(new_conn, result);
489 cli_shutdown(new_conn->cli);
496 /* Return true if a connection is still alive */
498 static BOOL connection_ok(struct winbindd_cm_conn *conn)
501 smb_panic("Invalid paramater passed to conneciton_ok(): conn was NULL!\n");
506 DEBUG(0, ("Connection to %s for domain %s (pipe %s) has NULL conn->cli!\n",
507 conn->controller, conn->domain, conn->pipe_name));
508 smb_panic("connection_ok: conn->cli was null!");
512 if (!conn->cli->initialised) {
513 DEBUG(0, ("Connection to %s for domain %s (pipe %s) was never initialised!\n",
514 conn->controller, conn->domain, conn->pipe_name));
515 smb_panic("connection_ok: conn->cli->initialised is False!");
519 if (conn->cli->fd == -1) {
520 DEBUG(3, ("Connection to %s for domain %s (pipe %s) has died or was never started (fd == -1)\n",
521 conn->controller, conn->domain, conn->pipe_name));
528 /* Get a connection to the remote DC and open the pipe. If there is already a connection, use that */
530 static NTSTATUS get_connection_from_cache(const char *domain, const char *pipe_name, struct winbindd_cm_conn **conn_out)
532 struct winbindd_cm_conn *conn, conn_temp;
535 for (conn = cm_conns; conn; conn = conn->next) {
536 if (strequal(conn->domain, domain) &&
537 strequal(conn->pipe_name, pipe_name)) {
538 if (!connection_ok(conn)) {
540 cli_shutdown(conn->cli);
542 ZERO_STRUCT(conn_temp);
543 conn_temp.next = conn->next;
544 DLIST_REMOVE(cm_conns, conn);
546 conn = &conn_temp; /* Just to keep the loop moving */
554 if (!(conn = malloc(sizeof(*conn))))
555 return NT_STATUS_NO_MEMORY;
559 if (!NT_STATUS_IS_OK(result = cm_open_connection(domain, get_pipe_index(pipe_name), conn))) {
560 DEBUG(3, ("Could not open a connection to %s for %s (%s)\n",
561 domain, pipe_name, nt_errstr(result)));
565 DLIST_ADD(cm_conns, conn);
573 /**********************************************************************************
574 **********************************************************************************/
576 BOOL cm_check_for_native_mode_win2k( const char *domain )
579 struct winbindd_cm_conn conn;
587 if ( !NT_STATUS_IS_OK(result = cm_open_connection(domain, PI_LSARPC_DS, &conn)) )
589 DEBUG(5, ("cm_check_for_native_mode_win2k: Could not open a connection to %s for PIPE_LSARPC (%s)\n",
590 domain, nt_errstr(result)));
595 if ( !NT_STATUS_IS_OK(cli_ds_getprimarydominfo( conn.cli,
596 conn.cli->mem_ctx, DsRolePrimaryDomainInfoBasic, &ctr)) )
603 if ( (ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING)
604 && !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE) )
611 cli_shutdown( conn.cli );
618 /* Return a LSA policy handle on a domain */
620 CLI_POLICY_HND *cm_get_lsa_handle(char *domain)
622 struct winbindd_cm_conn *conn;
623 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
625 static CLI_POLICY_HND hnd;
627 /* Look for existing connections */
629 if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_LSARPC, &conn))) {
633 /* This *shitty* code needs scrapping ! JRA */
634 if (policy_handle_is_valid(&conn->pol)) {
640 result = cli_lsa_open_policy(conn->cli, conn->cli->mem_ctx, False,
641 des_access, &conn->pol);
643 if (!NT_STATUS_IS_OK(result)) {
644 /* Hit the cache code again. This cleans out the old connection and gets a new one */
645 if (conn->cli->fd == -1) { /* Try again, if the remote host disapeared */
646 if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_LSARPC, &conn))) {
650 result = cli_lsa_open_policy(conn->cli, conn->cli->mem_ctx, False,
651 des_access, &conn->pol);
654 if (!NT_STATUS_IS_OK(result)) {
655 cli_shutdown(conn->cli);
656 DLIST_REMOVE(cm_conns, conn);
668 /* Return a SAM policy handle on a domain */
670 CLI_POLICY_HND *cm_get_sam_handle(char *domain)
672 struct winbindd_cm_conn *conn;
673 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
675 static CLI_POLICY_HND hnd;
677 /* Look for existing connections */
679 if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_SAMR, &conn))) {
683 /* This *shitty* code needs scrapping ! JRA */
684 if (policy_handle_is_valid(&conn->pol)) {
689 result = cli_samr_connect(conn->cli, conn->cli->mem_ctx,
690 des_access, &conn->pol);
692 if (!NT_STATUS_IS_OK(result)) {
693 /* Hit the cache code again. This cleans out the old connection and gets a new one */
694 if (conn->cli->fd == -1) { /* Try again, if the remote host disapeared */
695 if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_SAMR, &conn))) {
699 result = cli_samr_connect(conn->cli, conn->cli->mem_ctx,
700 des_access, &conn->pol);
703 if (!NT_STATUS_IS_OK(result)) {
704 cli_shutdown(conn->cli);
705 DLIST_REMOVE(cm_conns, conn);
717 #if 0 /* This code now *well* out of date */
719 /* Return a SAM domain policy handle on a domain */
721 CLI_POLICY_HND *cm_get_sam_dom_handle(char *domain, DOM_SID *domain_sid)
723 struct winbindd_cm_conn *conn, *basic_conn = NULL;
724 static CLI_POLICY_HND hnd;
726 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
728 /* Look for existing connections */
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) {
735 if (!connection_ok(conn)) {
736 /* Shutdown cli? Free conn? Allow retry of DC? */
737 DLIST_REMOVE(cm_conns, conn);
745 /* Create a basic handle to open a domain handle from */
747 if (!cm_get_sam_handle(domain))
750 for (conn = cm_conns; conn; conn = conn->next) {
751 if (strequal(conn->domain, domain) &&
752 strequal(conn->pipe_name, PIPE_SAMR) &&
753 conn->pipe_data.samr.pipe_type == SAM_PIPE_BASIC)
757 if (!(conn = (struct winbindd_cm_conn *)
758 malloc(sizeof(struct winbindd_cm_conn))))
763 fstrcpy(conn->domain, basic_conn->domain);
764 fstrcpy(conn->controller, basic_conn->controller);
765 fstrcpy(conn->pipe_name, basic_conn->pipe_name);
767 conn->pipe_data.samr.pipe_type = SAM_PIPE_DOM;
768 conn->cli = basic_conn->cli;
770 result = cli_samr_open_domain(conn->cli, conn->cli->mem_ctx,
771 &basic_conn->pol, des_access,
772 domain_sid, &conn->pol);
774 if (!NT_STATUS_IS_OK(result))
779 DLIST_ADD(cm_conns, conn);
788 /* Return a SAM policy handle on a domain user */
790 CLI_POLICY_HND *cm_get_sam_user_handle(char *domain, DOM_SID *domain_sid,
793 struct winbindd_cm_conn *conn, *basic_conn = NULL;
794 static CLI_POLICY_HND hnd;
796 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
798 /* Look for existing connections */
800 for (conn = cm_conns; conn; conn = conn->next) {
801 if (strequal(conn->domain, domain) &&
802 strequal(conn->pipe_name, PIPE_SAMR) &&
803 conn->pipe_data.samr.pipe_type == SAM_PIPE_USER &&
804 conn->pipe_data.samr.rid == user_rid) {
806 if (!connection_ok(conn)) {
807 /* Shutdown cli? Free conn? Allow retry of DC? */
808 DLIST_REMOVE(cm_conns, conn);
816 /* Create a domain handle to open a user handle from */
818 if (!cm_get_sam_dom_handle(domain, domain_sid))
821 for (conn = cm_conns; conn; conn = conn->next) {
822 if (strequal(conn->domain, domain) &&
823 strequal(conn->pipe_name, PIPE_SAMR) &&
824 conn->pipe_data.samr.pipe_type == SAM_PIPE_DOM)
829 DEBUG(0, ("No domain sam handle was created!\n"));
833 if (!(conn = (struct winbindd_cm_conn *)
834 malloc(sizeof(struct winbindd_cm_conn))))
839 fstrcpy(conn->domain, basic_conn->domain);
840 fstrcpy(conn->controller, basic_conn->controller);
841 fstrcpy(conn->pipe_name, basic_conn->pipe_name);
843 conn->pipe_data.samr.pipe_type = SAM_PIPE_USER;
844 conn->cli = basic_conn->cli;
845 conn->pipe_data.samr.rid = user_rid;
847 result = cli_samr_open_user(conn->cli, conn->cli->mem_ctx,
848 &basic_conn->pol, des_access, user_rid,
851 if (!NT_STATUS_IS_OK(result))
856 DLIST_ADD(cm_conns, conn);
865 /* Return a SAM policy handle on a domain group */
867 CLI_POLICY_HND *cm_get_sam_group_handle(char *domain, DOM_SID *domain_sid,
870 struct winbindd_cm_conn *conn, *basic_conn = NULL;
871 static CLI_POLICY_HND hnd;
873 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
875 /* Look for existing connections */
877 for (conn = cm_conns; conn; conn = conn->next) {
878 if (strequal(conn->domain, domain) &&
879 strequal(conn->pipe_name, PIPE_SAMR) &&
880 conn->pipe_data.samr.pipe_type == SAM_PIPE_GROUP &&
881 conn->pipe_data.samr.rid == group_rid) {
883 if (!connection_ok(conn)) {
884 /* Shutdown cli? Free conn? Allow retry of DC? */
885 DLIST_REMOVE(cm_conns, conn);
893 /* Create a domain handle to open a user handle from */
895 if (!cm_get_sam_dom_handle(domain, domain_sid))
898 for (conn = cm_conns; conn; conn = conn->next) {
899 if (strequal(conn->domain, domain) &&
900 strequal(conn->pipe_name, PIPE_SAMR) &&
901 conn->pipe_data.samr.pipe_type == SAM_PIPE_DOM)
906 DEBUG(0, ("No domain sam handle was created!\n"));
910 if (!(conn = (struct winbindd_cm_conn *)
911 malloc(sizeof(struct winbindd_cm_conn))))
916 fstrcpy(conn->domain, basic_conn->domain);
917 fstrcpy(conn->controller, basic_conn->controller);
918 fstrcpy(conn->pipe_name, basic_conn->pipe_name);
920 conn->pipe_data.samr.pipe_type = SAM_PIPE_GROUP;
921 conn->cli = basic_conn->cli;
922 conn->pipe_data.samr.rid = group_rid;
924 result = cli_samr_open_group(conn->cli, conn->cli->mem_ctx,
925 &basic_conn->pol, des_access, group_rid,
928 if (!NT_STATUS_IS_OK(result))
933 DLIST_ADD(cm_conns, conn);
944 /* Get a handle on a netlogon pipe. This is a bit of a hack to re-use the
945 netlogon pipe as no handle is returned. */
947 NTSTATUS cm_get_netlogon_cli(char *domain, unsigned char *trust_passwd,
948 struct cli_state **cli)
950 NTSTATUS result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
951 struct winbindd_cm_conn *conn;
952 uint32 neg_flags = 0x000001ff;
955 return NT_STATUS_INVALID_PARAMETER;
958 /* Open an initial conection */
960 if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_NETLOGON, &conn))) {
964 result = cli_nt_setup_creds(conn->cli, get_sec_chan(), trust_passwd, &neg_flags, 2);
966 if (!NT_STATUS_IS_OK(result)) {
967 DEBUG(0, ("error connecting to domain password server: %s\n",
970 /* Hit the cache code again. This cleans out the old connection and gets a new one */
971 if (conn->cli->fd == -1) {
972 if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_NETLOGON, &conn))) {
977 result = cli_nt_setup_creds( conn->cli, get_sec_chan(),trust_passwd, &neg_flags, 2);
980 if (!NT_STATUS_IS_OK(result)) {
981 cli_shutdown(conn->cli);
982 DLIST_REMOVE(cm_conns, conn);
993 /* Dump the current connection status */
995 static void dump_conn_list(void)
997 struct winbindd_cm_conn *con;
999 DEBUG(0, ("\tDomain Controller Pipe\n"));
1001 for(con = cm_conns; con; con = con->next) {
1004 /* Display pipe info */
1006 if (asprintf(&msg, "\t%-15s %-15s %-16s", con->domain, con->controller, con->pipe_name) < 0) {
1007 DEBUG(0, ("Error: not enough memory!\n"));
1009 DEBUG(0, ("%s\n", msg));
1015 void winbindd_cm_status(void)
1017 /* List open connections */
1019 DEBUG(0, ("winbindd connection manager status:\n"));
1024 DEBUG(0, ("\tNo active connections\n"));