diff options
Diffstat (limited to 'source4/nsswitch/winbindd_cm.c')
-rw-r--r-- | source4/nsswitch/winbindd_cm.c | 954 |
1 files changed, 0 insertions, 954 deletions
diff --git a/source4/nsswitch/winbindd_cm.c b/source4/nsswitch/winbindd_cm.c deleted file mode 100644 index 0748a1c534..0000000000 --- a/source4/nsswitch/winbindd_cm.c +++ /dev/null @@ -1,954 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind daemon connection manager - - Copyright (C) Tim Potter 2001 - Copyright (C) Andrew Bartlett 2002 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* - We need to manage connections to domain controllers without having to - mess up the main winbindd code with other issues. The aim of the - connection manager is to: - - - make connections to domain controllers and cache them - - re-establish connections when networks or servers go down - - centralise the policy on connection timeouts, domain controller - selection etc - - manage re-entrancy for when winbindd becomes able to handle - multiple outstanding rpc requests - - Why not have connection management as part of the rpc layer like tng? - Good question. This code may morph into libsmb/rpc_cache.c or something - like that but at the moment it's simply staying as part of winbind. I - think the TNG architecture of forcing every user of the rpc layer to use - the connection caching system is a bad idea. It should be an optional - method of using the routines. - - The TNG design is quite good but I disagree with some aspects of the - implementation. -tpot - - */ - -/* - TODO: - - - I'm pretty annoyed by all the make_nmb_name() stuff. It should be - moved down into another function. - - - There needs to be a utility function in libsmb/namequery.c that does - cm_get_dc_name() - - - Take care when destroying cli_structs as they can be shared between - various sam handles. - - */ - -#include "winbindd.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_WINBIND - -/* Global list of connections. Initially a DLIST but can become a hash - table or whatever later. */ - -struct winbindd_cm_conn { - struct winbindd_cm_conn *prev, *next; - fstring domain; - fstring controller; - fstring pipe_name; - size_t mutex_ref_count; - struct cli_state *cli; - POLICY_HND pol; -}; - -static struct winbindd_cm_conn *cm_conns = NULL; - -/* Get a domain controller name. Cache positive and negative lookups so we - don't go to the network too often when something is badly broken. */ - -#define GET_DC_NAME_CACHE_TIMEOUT 30 /* Seconds between dc lookups */ - -struct get_dc_name_cache { - fstring domain_name; - fstring srv_name; - time_t lookup_time; - struct get_dc_name_cache *prev, *next; -}; - -/* - find the DC for a domain using methods appropriate for a ADS domain -*/ -static BOOL cm_ads_find_dc(const char *domain, struct in_addr *dc_ip, fstring srv_name) -{ - ADS_STRUCT *ads; - const char *realm = domain; - - if (strcasecmp(realm, lp_workgroup()) == 0) - realm = lp_realm(); - - ads = ads_init(realm, domain, NULL); - if (!ads) - return False; - - /* we don't need to bind, just connect */ - ads->auth.flags |= ADS_AUTH_NO_BIND; - - DEBUG(4,("cm_ads_find_dc: domain=%s\n", domain)); - -#ifdef HAVE_ADS - /* a full ads_connect() is actually overkill, as we don't srictly need - to do the SASL auth in order to get the info we need, but libads - doesn't offer a better way right now */ - ads_connect(ads); -#endif - - if (!ads->config.realm) - return False; - - fstrcpy(srv_name, ads->config.ldap_server_name); - strupper(srv_name); - *dc_ip = ads->ldap_ip; - ads_destroy(&ads); - - DEBUG(4,("cm_ads_find_dc: using server='%s' IP=%s\n", - srv_name, inet_ntoa(*dc_ip))); - - return True; -} - - - -static BOOL cm_get_dc_name(const char *domain, fstring srv_name, struct in_addr *ip_out) -{ - static struct get_dc_name_cache *get_dc_name_cache; - struct get_dc_name_cache *dcc; - struct in_addr dc_ip; - BOOL ret; - - /* Check the cache for previous lookups */ - - for (dcc = get_dc_name_cache; dcc; dcc = dcc->next) { - - if (!strequal(domain, dcc->domain_name)) - continue; /* Not our domain */ - - if ((time(NULL) - dcc->lookup_time) > - GET_DC_NAME_CACHE_TIMEOUT) { - - /* Cache entry has expired, delete it */ - - DEBUG(10, ("get_dc_name_cache entry expired for %s\n", domain)); - - DLIST_REMOVE(get_dc_name_cache, dcc); - SAFE_FREE(dcc); - - break; - } - - /* Return a positive or negative lookup for this domain */ - - if (dcc->srv_name[0]) { - DEBUG(10, ("returning positive get_dc_name_cache entry for %s\n", domain)); - fstrcpy(srv_name, dcc->srv_name); - return True; - } else { - DEBUG(10, ("returning negative get_dc_name_cache entry for %s\n", domain)); - return False; - } - } - - /* Add cache entry for this lookup. */ - - DEBUG(10, ("Creating get_dc_name_cache entry for %s\n", domain)); - - if (!(dcc = (struct get_dc_name_cache *) - malloc(sizeof(struct get_dc_name_cache)))) - return False; - - ZERO_STRUCTP(dcc); - - fstrcpy(dcc->domain_name, domain); - dcc->lookup_time = time(NULL); - - DLIST_ADD(get_dc_name_cache, dcc); - - zero_ip(&dc_ip); - - ret = False; - if (lp_security() == SEC_ADS) - ret = cm_ads_find_dc(domain, &dc_ip, srv_name); - - if (!ret) { - /* fall back on rpc methods if the ADS methods fail */ - ret = rpc_find_dc(domain, srv_name, &dc_ip); - } - - if (!ret) - return False; - - /* We have a name so make the cache entry positive now */ - fstrcpy(dcc->srv_name, srv_name); - - DEBUG(3, ("cm_get_dc_name: Returning DC %s (%s) for domain %s\n", srv_name, - inet_ntoa(dc_ip), domain)); - - *ip_out = dc_ip; - - return True; -} - -/* Choose between anonymous or authenticated connections. We need to use - an authenticated connection if DCs have the RestrictAnonymous registry - entry set > 0, or the "Additional restrictions for anonymous - connections" set in the win2k Local Security Policy. - - Caller to free() result in domain, username, password -*/ - -static void cm_get_ipc_userpass(char **username, char **domain, char **password) -{ - *username = secrets_fetch(SECRETS_AUTH_USER, NULL); - *domain = secrets_fetch(SECRETS_AUTH_DOMAIN, NULL); - *password = secrets_fetch(SECRETS_AUTH_PASSWORD, NULL); - - if (*username && **username) { - - if (!*domain || !**domain) - *domain = smb_xstrdup(lp_workgroup()); - - if (!*password || !**password) - *password = smb_xstrdup(""); - - DEBUG(3, ("IPC$ connections done by user %s\\%s\n", - *domain, *username)); - - } else { - DEBUG(3, ("IPC$ connections done anonymously\n")); - *username = smb_xstrdup(""); - *domain = smb_xstrdup(""); - *password = smb_xstrdup(""); - } -} - -/* Open a new smb pipe connection to a DC on a given domain. Cache - negative creation attempts so we don't try and connect to broken - machines too often. */ - -#define FAILED_CONNECTION_CACHE_TIMEOUT 30 /* Seconds between attempts */ - -struct failed_connection_cache { - fstring domain_name; - fstring controller; - time_t lookup_time; - NTSTATUS nt_status; - struct failed_connection_cache *prev, *next; -}; - -static struct failed_connection_cache *failed_connection_cache; - -/* Add an entry to the failed conneciton cache */ - -static void add_failed_connection_entry(struct winbindd_cm_conn *new_conn, - NTSTATUS result) -{ - struct failed_connection_cache *fcc; - - SMB_ASSERT(!NT_STATUS_IS_OK(result)); - - /* Check we already aren't in the cache */ - - for (fcc = failed_connection_cache; fcc; fcc = fcc->next) { - if (strequal(fcc->domain_name, new_conn->domain)) { - DEBUG(10, ("domain %s already tried and failed\n", - fcc->domain_name)); - return; - } - } - - /* Create negative lookup cache entry for this domain and controller */ - - if (!(fcc = (struct failed_connection_cache *) - malloc(sizeof(struct failed_connection_cache)))) { - DEBUG(0, ("malloc failed in add_failed_connection_entry!\n")); - return; - } - - ZERO_STRUCTP(fcc); - - fstrcpy(fcc->domain_name, new_conn->domain); - fstrcpy(fcc->controller, new_conn->controller); - fcc->lookup_time = time(NULL); - fcc->nt_status = result; - - DLIST_ADD(failed_connection_cache, fcc); -} - -/* Open a connction to the remote server, cache failures for 30 seconds */ - -static NTSTATUS cm_open_connection(const char *domain, const int pipe_index, - struct winbindd_cm_conn *new_conn, BOOL keep_mutex) -{ - struct failed_connection_cache *fcc; - NTSTATUS result; - char *ipc_username, *ipc_domain, *ipc_password; - struct in_addr dc_ip; - int i; - BOOL retry = True; - BOOL got_mutex = False; - - ZERO_STRUCT(dc_ip); - - fstrcpy(new_conn->domain, domain); - fstrcpy(new_conn->pipe_name, get_pipe_name_from_index(pipe_index)); - - /* Look for a domain controller for this domain. Negative results - are cached so don't bother applying the caching for this - function just yet. */ - - if (!cm_get_dc_name(domain, new_conn->controller, &dc_ip)) { - result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; - add_failed_connection_entry(new_conn, result); - return result; - } - - /* Return false if we have tried to look up this domain and netbios - name before and failed. */ - - for (fcc = failed_connection_cache; fcc; fcc = fcc->next) { - - if (!(strequal(domain, fcc->domain_name) && - strequal(new_conn->controller, fcc->controller))) - continue; /* Not our domain */ - - if ((time(NULL) - fcc->lookup_time) > - FAILED_CONNECTION_CACHE_TIMEOUT) { - - /* Cache entry has expired, delete it */ - - DEBUG(10, ("cm_open_connection cache entry expired for %s, %s\n", domain, new_conn->controller)); - - DLIST_REMOVE(failed_connection_cache, fcc); - free(fcc); - - break; - } - - /* The timeout hasn't expired yet so return false */ - - DEBUG(10, ("returning negative open_connection_cache entry for %s, %s\n", domain, new_conn->controller)); - - result = fcc->nt_status; - SMB_ASSERT(!NT_STATUS_IS_OK(result)); - return result; - } - - /* Initialise SMB connection */ - - cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password); - - DEBUG(5, ("connecting to %s from %s with username [%s]\\[%s]\n", - new_conn->controller, lp_netbios_name(), ipc_domain, ipc_username)); - - for (i = 0; retry && (i < 3); i++) { - - if (!secrets_named_mutex(new_conn->controller, WINBIND_SERVER_MUTEX_WAIT_TIME, &new_conn->mutex_ref_count)) { - DEBUG(0,("cm_open_connection: mutex grab failed for %s\n", new_conn->controller)); - result = NT_STATUS_POSSIBLE_DEADLOCK; - continue; - } - - got_mutex = True; - - result = cli_full_connection(&new_conn->cli, lp_netbios_name(), new_conn->controller, - &dc_ip, 0, "IPC$", "IPC", ipc_username, ipc_domain, - ipc_password, 0, &retry); - - if (NT_STATUS_IS_OK(result)) - break; - - secrets_named_mutex_release(new_conn->controller, &new_conn->mutex_ref_count); - got_mutex = False; - } - - SAFE_FREE(ipc_username); - SAFE_FREE(ipc_domain); - SAFE_FREE(ipc_password); - - if (!NT_STATUS_IS_OK(result)) { - if (got_mutex) - secrets_named_mutex_release(new_conn->controller, &new_conn->mutex_ref_count); - add_failed_connection_entry(new_conn, result); - return result; - } - - if ( !cli_nt_session_open (new_conn->cli, pipe_index) ) { - result = NT_STATUS_PIPE_NOT_AVAILABLE; - /* - * only cache a failure if we are not trying to open the - * **win2k** specific lsarpc UUID. This could be an NT PDC - * and therefore a failure is normal. This should probably - * be abstracted to a check for 2k specific pipes and wondering - * if the PDC is an NT4 box. but since there is only one 2k - * specific UUID right now, i'm not going to bother. --jerry - */ - if (got_mutex) - secrets_named_mutex_release(new_conn->controller, &new_conn->mutex_ref_count); - if ( !is_win2k_pipe(pipe_index) ) - add_failed_connection_entry(new_conn, result); - cli_shutdown(new_conn->cli); - return result; - } - - if ((got_mutex) && !keep_mutex) - secrets_named_mutex_release(new_conn->controller, &new_conn->mutex_ref_count); - return NT_STATUS_OK; -} - -/* Return true if a connection is still alive */ - -static BOOL connection_ok(struct winbindd_cm_conn *conn) -{ - if (!conn) { - smb_panic("Invalid paramater passed to conneciton_ok(): conn was NULL!\n"); - return False; - } - - if (!conn->cli) { - DEBUG(0, ("Connection to %s for domain %s (pipe %s) has NULL conn->cli!\n", - conn->controller, conn->domain, conn->pipe_name)); - smb_panic("connection_ok: conn->cli was null!"); - return False; - } - - if (!conn->cli->initialised) { - DEBUG(0, ("Connection to %s for domain %s (pipe %s) was never initialised!\n", - conn->controller, conn->domain, conn->pipe_name)); - smb_panic("connection_ok: conn->cli->initialised is False!"); - return False; - } - - if (conn->cli->fd == -1) { - DEBUG(3, ("Connection to %s for domain %s (pipe %s) has died or was never started (fd == -1)\n", - conn->controller, conn->domain, conn->pipe_name)); - return False; - } - - return True; -} - -/* Get a connection to the remote DC and open the pipe. If there is already a connection, use that */ - -static NTSTATUS get_connection_from_cache(const char *domain, const char *pipe_name, - struct winbindd_cm_conn **conn_out, BOOL keep_mutex) -{ - struct winbindd_cm_conn *conn, conn_temp; - NTSTATUS result; - - for (conn = cm_conns; conn; conn = conn->next) { - if (strequal(conn->domain, domain) && - strequal(conn->pipe_name, pipe_name)) { - if (!connection_ok(conn)) { - if (conn->cli) - cli_shutdown(conn->cli); - ZERO_STRUCT(conn_temp); - conn_temp.next = conn->next; - DLIST_REMOVE(cm_conns, conn); - SAFE_FREE(conn); - conn = &conn_temp; /* Just to keep the loop moving */ - } else { - if (keep_mutex) { - if (!secrets_named_mutex(conn->controller, - WINBIND_SERVER_MUTEX_WAIT_TIME, &conn->mutex_ref_count)) - DEBUG(0,("get_connection_from_cache: mutex grab failed for %s\n", - conn->controller)); - } - break; - } - } - } - - if (!conn) { - if (!(conn = malloc(sizeof(*conn)))) - return NT_STATUS_NO_MEMORY; - - ZERO_STRUCTP(conn); - - if (!NT_STATUS_IS_OK(result = cm_open_connection(domain, get_pipe_index(pipe_name), conn, keep_mutex))) { - DEBUG(3, ("Could not open a connection to %s for %s (%s)\n", - domain, pipe_name, nt_errstr(result))); - SAFE_FREE(conn); - return result; - } - DLIST_ADD(cm_conns, conn); - } - - *conn_out = conn; - return NT_STATUS_OK; -} - - -/********************************************************************************** -**********************************************************************************/ - -BOOL cm_check_for_native_mode_win2k( const char *domain ) -{ - NTSTATUS result; - struct winbindd_cm_conn conn; - DS_DOMINFO_CTR ctr; - BOOL ret = False; - - ZERO_STRUCT( conn ); - ZERO_STRUCT( ctr ); - - - if ( !NT_STATUS_IS_OK(result = cm_open_connection(domain, PI_LSARPC_DS, &conn, False)) ) { - DEBUG(5, ("cm_check_for_native_mode_win2k: Could not open a connection to %s for PIPE_LSARPC (%s)\n", - domain, nt_errstr(result))); - return False; - } - - if ( conn.cli ) { - if ( !NT_STATUS_IS_OK(cli_ds_getprimarydominfo( conn.cli, - conn.cli->mem_ctx, DsRolePrimaryDomainInfoBasic, &ctr)) ) { - ret = False; - goto done; - } - } - - if ( (ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) - && !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE) ) - ret = True; - -done: - if ( conn.cli ) - cli_shutdown( conn.cli ); - - return ret; -} - - - -/* Return a LSA policy handle on a domain */ - -CLI_POLICY_HND *cm_get_lsa_handle(const char *domain) -{ - struct winbindd_cm_conn *conn; - uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; - NTSTATUS result; - static CLI_POLICY_HND hnd; - - /* Look for existing connections */ - - if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_LSARPC, &conn, False))) - return NULL; - - /* This *shitty* code needs scrapping ! JRA */ - if (policy_handle_is_valid(&conn->pol)) { - hnd.pol = conn->pol; - hnd.cli = conn->cli; - return &hnd; - } - - result = cli_lsa_open_policy(conn->cli, conn->cli->mem_ctx, False, - des_access, &conn->pol); - - if (!NT_STATUS_IS_OK(result)) { - /* Hit the cache code again. This cleans out the old connection and gets a new one */ - if (conn->cli->fd == -1) { /* Try again, if the remote host disapeared */ - if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_LSARPC, &conn, False))) - return NULL; - - result = cli_lsa_open_policy(conn->cli, conn->cli->mem_ctx, False, - des_access, &conn->pol); - } - - if (!NT_STATUS_IS_OK(result)) { - cli_shutdown(conn->cli); - DLIST_REMOVE(cm_conns, conn); - SAFE_FREE(conn); - return NULL; - } - } - - hnd.pol = conn->pol; - hnd.cli = conn->cli; - - return &hnd; -} - -/* Return a SAM policy handle on a domain */ - -CLI_POLICY_HND *cm_get_sam_handle(char *domain) -{ - struct winbindd_cm_conn *conn; - uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; - NTSTATUS result; - static CLI_POLICY_HND hnd; - - /* Look for existing connections */ - - if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_SAMR, &conn, False))) - return NULL; - - /* This *shitty* code needs scrapping ! JRA */ - if (policy_handle_is_valid(&conn->pol)) { - hnd.pol = conn->pol; - hnd.cli = conn->cli; - return &hnd; - } - result = cli_samr_connect(conn->cli, conn->cli->mem_ctx, - des_access, &conn->pol); - - if (!NT_STATUS_IS_OK(result)) { - /* Hit the cache code again. This cleans out the old connection and gets a new one */ - if (conn->cli->fd == -1) { /* Try again, if the remote host disapeared */ - if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_SAMR, &conn, False))) - return NULL; - - result = cli_samr_connect(conn->cli, conn->cli->mem_ctx, - des_access, &conn->pol); - } - - if (!NT_STATUS_IS_OK(result)) { - cli_shutdown(conn->cli); - DLIST_REMOVE(cm_conns, conn); - SAFE_FREE(conn); - return NULL; - } - } - - hnd.pol = conn->pol; - hnd.cli = conn->cli; - - return &hnd; -} - -#if 0 /* This code now *well* out of date */ - -/* Return a SAM domain policy handle on a domain */ - -CLI_POLICY_HND *cm_get_sam_dom_handle(char *domain, DOM_SID *domain_sid) -{ - struct winbindd_cm_conn *conn, *basic_conn = NULL; - static CLI_POLICY_HND hnd; - NTSTATUS result; - uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; - - /* Look for existing connections */ - - for (conn = cm_conns; conn; conn = conn->next) { - if (strequal(conn->domain, domain) && - strequal(conn->pipe_name, PIPE_SAMR) && - conn->pipe_data.samr.pipe_type == SAM_PIPE_DOM) { - - if (!connection_ok(conn)) { - /* Shutdown cli? Free conn? Allow retry of DC? */ - DLIST_REMOVE(cm_conns, conn); - return NULL; - } - - goto ok; - } - } - - /* Create a basic handle to open a domain handle from */ - - if (!cm_get_sam_handle(domain)) - return False; - - for (conn = cm_conns; conn; conn = conn->next) { - if (strequal(conn->domain, domain) && - strequal(conn->pipe_name, PIPE_SAMR) && - conn->pipe_data.samr.pipe_type == SAM_PIPE_BASIC) - basic_conn = conn; - } - - if (!(conn = (struct winbindd_cm_conn *) - malloc(sizeof(struct winbindd_cm_conn)))) - return NULL; - - ZERO_STRUCTP(conn); - - fstrcpy(conn->domain, basic_conn->domain); - fstrcpy(conn->controller, basic_conn->controller); - fstrcpy(conn->pipe_name, basic_conn->pipe_name); - - conn->pipe_data.samr.pipe_type = SAM_PIPE_DOM; - conn->cli = basic_conn->cli; - - result = cli_samr_open_domain(conn->cli, conn->cli->mem_ctx, - &basic_conn->pol, des_access, - domain_sid, &conn->pol); - - if (!NT_STATUS_IS_OK(result)) - return NULL; - - /* Add to list */ - - DLIST_ADD(cm_conns, conn); - - ok: - hnd.pol = conn->pol; - hnd.cli = conn->cli; - - return &hnd; -} - -/* Return a SAM policy handle on a domain user */ - -CLI_POLICY_HND *cm_get_sam_user_handle(char *domain, DOM_SID *domain_sid, - uint32 user_rid) -{ - struct winbindd_cm_conn *conn, *basic_conn = NULL; - static CLI_POLICY_HND hnd; - NTSTATUS result; - uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; - - /* Look for existing connections */ - - for (conn = cm_conns; conn; conn = conn->next) { - if (strequal(conn->domain, domain) && - strequal(conn->pipe_name, PIPE_SAMR) && - conn->pipe_data.samr.pipe_type == SAM_PIPE_USER && - conn->pipe_data.samr.rid == user_rid) { - - if (!connection_ok(conn)) { - /* Shutdown cli? Free conn? Allow retry of DC? */ - DLIST_REMOVE(cm_conns, conn); - return NULL; - } - - goto ok; - } - } - - /* Create a domain handle to open a user handle from */ - - if (!cm_get_sam_dom_handle(domain, domain_sid)) - return NULL; - - for (conn = cm_conns; conn; conn = conn->next) { - if (strequal(conn->domain, domain) && - strequal(conn->pipe_name, PIPE_SAMR) && - conn->pipe_data.samr.pipe_type == SAM_PIPE_DOM) - basic_conn = conn; - } - - if (!basic_conn) { - DEBUG(0, ("No domain sam handle was created!\n")); - return NULL; - } - - if (!(conn = (struct winbindd_cm_conn *) - malloc(sizeof(struct winbindd_cm_conn)))) - return NULL; - - ZERO_STRUCTP(conn); - - fstrcpy(conn->domain, basic_conn->domain); - fstrcpy(conn->controller, basic_conn->controller); - fstrcpy(conn->pipe_name, basic_conn->pipe_name); - - conn->pipe_data.samr.pipe_type = SAM_PIPE_USER; - conn->cli = basic_conn->cli; - conn->pipe_data.samr.rid = user_rid; - - result = cli_samr_open_user(conn->cli, conn->cli->mem_ctx, - &basic_conn->pol, des_access, user_rid, - &conn->pol); - - if (!NT_STATUS_IS_OK(result)) - return NULL; - - /* Add to list */ - - DLIST_ADD(cm_conns, conn); - - ok: - hnd.pol = conn->pol; - hnd.cli = conn->cli; - - return &hnd; -} - -/* Return a SAM policy handle on a domain group */ - -CLI_POLICY_HND *cm_get_sam_group_handle(char *domain, DOM_SID *domain_sid, - uint32 group_rid) -{ - struct winbindd_cm_conn *conn, *basic_conn = NULL; - static CLI_POLICY_HND hnd; - NTSTATUS result; - uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; - - /* Look for existing connections */ - - for (conn = cm_conns; conn; conn = conn->next) { - if (strequal(conn->domain, domain) && - strequal(conn->pipe_name, PIPE_SAMR) && - conn->pipe_data.samr.pipe_type == SAM_PIPE_GROUP && - conn->pipe_data.samr.rid == group_rid) { - - if (!connection_ok(conn)) { - /* Shutdown cli? Free conn? Allow retry of DC? */ - DLIST_REMOVE(cm_conns, conn); - return NULL; - } - - goto ok; - } - } - - /* Create a domain handle to open a user handle from */ - - if (!cm_get_sam_dom_handle(domain, domain_sid)) - return NULL; - - for (conn = cm_conns; conn; conn = conn->next) { - if (strequal(conn->domain, domain) && - strequal(conn->pipe_name, PIPE_SAMR) && - conn->pipe_data.samr.pipe_type == SAM_PIPE_DOM) - basic_conn = conn; - } - - if (!basic_conn) { - DEBUG(0, ("No domain sam handle was created!\n")); - return NULL; - } - - if (!(conn = (struct winbindd_cm_conn *) - malloc(sizeof(struct winbindd_cm_conn)))) - return NULL; - - ZERO_STRUCTP(conn); - - fstrcpy(conn->domain, basic_conn->domain); - fstrcpy(conn->controller, basic_conn->controller); - fstrcpy(conn->pipe_name, basic_conn->pipe_name); - - conn->pipe_data.samr.pipe_type = SAM_PIPE_GROUP; - conn->cli = basic_conn->cli; - conn->pipe_data.samr.rid = group_rid; - - result = cli_samr_open_group(conn->cli, conn->cli->mem_ctx, - &basic_conn->pol, des_access, group_rid, - &conn->pol); - - if (!NT_STATUS_IS_OK(result)) - return NULL; - - /* Add to list */ - - DLIST_ADD(cm_conns, conn); - - ok: - hnd.pol = conn->pol; - hnd.cli = conn->cli; - - return &hnd; -} - -#endif - -/* Get a handle on a netlogon pipe. This is a bit of a hack to re-use the - netlogon pipe as no handle is returned. */ - -NTSTATUS cm_get_netlogon_cli(const char *domain, const unsigned char *trust_passwd, - struct cli_state **cli) -{ - NTSTATUS result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; - struct winbindd_cm_conn *conn; - uint32 neg_flags = 0x000001ff; - - if (!cli) - return NT_STATUS_INVALID_PARAMETER; - - /* Open an initial conection - keep the mutex. */ - - if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_NETLOGON, &conn, True))) - return result; - - result = cli_nt_setup_creds(conn->cli, get_sec_chan(), trust_passwd, &neg_flags, 2); - - if (conn->mutex_ref_count) - secrets_named_mutex_release(conn->controller, &conn->mutex_ref_count); - - if (!NT_STATUS_IS_OK(result)) { - DEBUG(0, ("error connecting to domain password server: %s\n", - nt_errstr(result))); - - /* Hit the cache code again. This cleans out the old connection and gets a new one */ - if (conn->cli->fd == -1) { - - if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_NETLOGON, &conn, True))) - return result; - - /* Try again */ - result = cli_nt_setup_creds( conn->cli, get_sec_chan(),trust_passwd, &neg_flags, 2); - - if (conn->mutex_ref_count) - secrets_named_mutex_release(conn->controller, &conn->mutex_ref_count); - } - - if (!NT_STATUS_IS_OK(result)) { - cli_shutdown(conn->cli); - DLIST_REMOVE(cm_conns, conn); - SAFE_FREE(conn); - return result; - } - } - - *cli = conn->cli; - - return result; -} - -/* Dump the current connection status */ - -static void dump_conn_list(void) -{ - struct winbindd_cm_conn *con; - - DEBUG(0, ("\tDomain Controller Pipe\n")); - - for(con = cm_conns; con; con = con->next) { - char *msg; - - /* Display pipe info */ - - if (asprintf(&msg, "\t%-15s %-15s %-16s", con->domain, con->controller, con->pipe_name) < 0) { - DEBUG(0, ("Error: not enough memory!\n")); - } else { - DEBUG(0, ("%s\n", msg)); - SAFE_FREE(msg); - } - } -} - -void winbindd_cm_status(void) -{ - /* List open connections */ - - DEBUG(0, ("winbindd connection manager status:\n")); - - if (cm_conns) - dump_conn_list(); - else - DEBUG(0, ("\tNo active connections\n")); -} |