X-Git-Url: http://git.samba.org/samba.git/?p=nivanova%2Fsamba-autobuild%2F.git;a=blobdiff_plain;f=source3%2Fnsswitch%2Fwinbindd_cm.c;h=381cdaaa20f258bfe7390830ca5b4644e566075e;hp=bbf5b90495ebfbb4bad4f30e1b7f984fb155a55f;hb=3ef930a8e9f4574b697968e15b2468aa01863929;hpb=500905fedb0ff6b054ea121e8b42529d69a16ae7 diff --git a/source3/nsswitch/winbindd_cm.c b/source3/nsswitch/winbindd_cm.c index bbf5b90495e..381cdaaa20f 100644 --- a/source3/nsswitch/winbindd_cm.c +++ b/source3/nsswitch/winbindd_cm.c @@ -72,6 +72,7 @@ struct winbindd_cm_conn { fstring domain; fstring controller; fstring pipe_name; + size_t mutex_ref_count; struct cli_state *cli; POLICY_HND pol; }; @@ -90,7 +91,6 @@ struct get_dc_name_cache { struct get_dc_name_cache *prev, *next; }; - /* find the DC for a domain using methods appropriate for a ADS domain */ @@ -99,14 +99,12 @@ static BOOL cm_ads_find_dc(const char *domain, struct in_addr *dc_ip, fstring sr ADS_STRUCT *ads; const char *realm = domain; - if (strcasecmp(realm, lp_workgroup()) == 0) { + if (strcasecmp(realm, lp_workgroup()) == 0) realm = lp_realm(); - } ads = ads_init(realm, domain, NULL); - if (!ads) { + if (!ads) return False; - } /* we don't need to bind, just connect */ ads->auth.flags |= ADS_AUTH_NO_BIND; @@ -120,9 +118,8 @@ static BOOL cm_ads_find_dc(const char *domain, struct in_addr *dc_ip, fstring sr ads_connect(ads); #endif - if (!ads->config.realm) { + if (!ads->config.realm) return False; - } fstrcpy(srv_name, ads->config.ldap_server_name); strupper(srv_name); @@ -135,90 +132,6 @@ static BOOL cm_ads_find_dc(const char *domain, struct in_addr *dc_ip, fstring sr return True; } -/* - find the DC for a domain using methods appropriate for a RPC domain -*/ -static BOOL cm_rpc_find_dc(const char *domain, struct in_addr *dc_ip, fstring srv_name) -{ - struct in_addr *ip_list = NULL, exclude_ip; - int count, i; - - zero_ip(&exclude_ip); - - /* Lookup domain controller name. Try the real PDC first to avoid - SAM sync delays */ - - if (get_dc_list(True, domain, &ip_list, &count)) { - if (name_status_find(domain, 0x1c, 0x20, ip_list[0], srv_name)) { - *dc_ip = ip_list[0]; - SAFE_FREE(ip_list); - return True; - } - /* Didn't get name, remember not to talk to this DC. */ - exclude_ip = ip_list[0]; - SAFE_FREE(ip_list); - } - - if (!get_dc_list(False, domain, &ip_list, &count)) { - DEBUG(3, ("Could not look up dc's for domain %s\n", domain)); - return False; - } - - /* Remove the entry we've already failed with (should be the PDC). */ - for (i = 0; i < count; i++) { - if (ip_equal( exclude_ip, ip_list[i])) - zero_ip(&ip_list[i]); - } - - /* Pick a nice close server */ - /* Look for DC on local net */ - for (i = 0; i < count; i++) { - if (is_zero_ip(ip_list[i])) - continue; - - if (!is_local_net(ip_list[i])) - continue; - - if (name_status_find(domain, 0x1c, 0x20, ip_list[i], srv_name)) { - *dc_ip = ip_list[i]; - SAFE_FREE(ip_list); - return True; - } - zero_ip(&ip_list[i]); - } - - /* - * Secondly try and contact a random PDC/BDC. - */ - - i = (sys_random() % count); - - if (!is_zero_ip(ip_list[i]) && - name_status_find(domain, 0x1c, 0x20, - ip_list[i], srv_name)) { - *dc_ip = ip_list[i]; - SAFE_FREE(ip_list); - return True; - } - zero_ip(&ip_list[i]); /* Tried and failed. */ - - /* Finally return first DC that we can contact using a node - status */ - for (i = 0; i < count; i++) { - if (is_zero_ip(ip_list[i])) - continue; - - if (name_status_find(domain, 0x1c, 0x20, ip_list[i], srv_name)) { - *dc_ip = ip_list[i]; - SAFE_FREE(ip_list); - return True; - } - } - - SAFE_FREE(ip_list); - - return False; -} static BOOL cm_get_dc_name(const char *domain, fstring srv_name, struct in_addr *ip_out) @@ -278,17 +191,16 @@ static BOOL cm_get_dc_name(const char *domain, fstring srv_name, struct in_addr zero_ip(&dc_ip); ret = False; - if (lp_security() == SEC_ADS) { + 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 = cm_rpc_find_dc(domain, &dc_ip, srv_name); + ret = rpc_find_dc(domain, srv_name, &dc_ip); } - if (!ret) { + if (!ret) return False; - } /* We have a name so make the cache entry positive now */ fstrcpy(dcc->srv_name, srv_name); @@ -334,66 +246,11 @@ static void cm_get_ipc_userpass(char **username, char **domain, char **password) } } -/* 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) { - struct failed_connection_cache *fcc; - extern pstring global_myname; NTSTATUS result; char *ipc_username, *ipc_domain, *ipc_password; struct in_addr dc_ip; @@ -405,65 +262,34 @@ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index, 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. */ + /* connection failure cache has been moved inside of get_dc_name + so we can deal with half dead DC's --jerry */ 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); + add_failed_connection_entry(domain, "", 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, global_myname, ipc_domain, ipc_username)); + new_conn->controller, global_myname(), ipc_domain, ipc_username)); for (i = 0; retry && (i < 3); i++) { - - if (!secrets_named_mutex(new_conn->controller, 10)) { + BOOL got_mutex; + if (!(got_mutex = secrets_named_mutex(new_conn->controller, WINBIND_SERVER_MUTEX_WAIT_TIME))) { DEBUG(0,("cm_open_connection: mutex grab failed for %s\n", new_conn->controller)); + result = NT_STATUS_POSSIBLE_DEADLOCK; continue; } - - result = cli_full_connection(&(new_conn->cli), global_myname, new_conn->controller, - &dc_ip, 0, "IPC$", "IPC", ipc_username, ipc_domain, - ipc_password, 0, &retry); - + + result = cli_full_connection(&new_conn->cli, global_myname(), new_conn->controller, + &dc_ip, 0, "IPC$", "IPC", ipc_username, ipc_domain, + ipc_password, CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK, &retry); + secrets_named_mutex_release(new_conn->controller); if (NT_STATUS_IS_OK(result)) @@ -475,7 +301,7 @@ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index, SAFE_FREE(ipc_password); if (!NT_STATUS_IS_OK(result)) { - add_failed_connection_entry(new_conn, result); + add_failed_connection_entry(domain, new_conn->controller, result); return result; } @@ -490,7 +316,7 @@ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index, * specific UUID right now, i'm not going to bother. --jerry */ if ( !is_win2k_pipe(pipe_index) ) - add_failed_connection_entry(new_conn, result); + add_failed_connection_entry(domain, new_conn->controller, result); cli_shutdown(new_conn->cli); return result; } @@ -503,21 +329,19 @@ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index, static BOOL connection_ok(struct winbindd_cm_conn *conn) { if (!conn) { - smb_panic("Invalid paramater passed to conneciton_ok(): conn was NULL!\n"); + smb_panic("Invalid parameter passed to connection_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", + DEBUG(3, ("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", + DEBUG(3, ("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; } @@ -530,50 +354,73 @@ static BOOL connection_ok(struct winbindd_cm_conn *conn) return True; } -/* Get a connection to the remote DC and open the pipe. If there is already a connection, use that */ +/* Search the cache for a connection. If there is a broken one, + shut it down properly and return NULL. */ -static NTSTATUS get_connection_from_cache(const char *domain, const char *pipe_name, struct winbindd_cm_conn **conn_out) +static void find_cm_connection(const char *domain, const char *pipe_name, + struct winbindd_cm_conn **conn_out) { - struct winbindd_cm_conn *conn, conn_temp; - NTSTATUS result; + struct winbindd_cm_conn *conn; - for (conn = cm_conns; conn; conn = conn->next) { + for (conn = cm_conns; conn; ) { if (strequal(conn->domain, domain) && strequal(conn->pipe_name, pipe_name)) { if (!connection_ok(conn)) { - if (conn->cli) { + /* Dead connection - remove it. */ + struct winbindd_cm_conn *conn_temp = conn->next; + 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 */ + conn = conn_temp; /* Keep the loop moving */ + continue; } else { break; } } + conn = conn->next; } - - if (!conn) { - if (!(conn = malloc(sizeof(*conn)))) - return NT_STATUS_NO_MEMORY; + + *conn_out = conn; +} + +/* Initialize a new connection up to the RPC BIND. */ + +static NTSTATUS new_cm_connection(const char *domain, const char *pipe_name, + struct winbindd_cm_conn **conn_out) +{ + struct winbindd_cm_conn *conn; + NTSTATUS result; + + if (!(conn = malloc(sizeof(*conn)))) + return NT_STATUS_NO_MEMORY; - ZERO_STRUCTP(conn); + ZERO_STRUCTP(conn); - if (!NT_STATUS_IS_OK(result = cm_open_connection(domain, get_pipe_index(pipe_name), conn))) { - 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); + if (!NT_STATUS_IS_OK(result = cm_open_connection(domain, get_pipe_index(pipe_name), conn))) { + 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; } +/* 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) +{ + find_cm_connection(domain, pipe_name, conn_out); + + if (*conn_out != NULL) + return NT_STATUS_OK; + + return new_cm_connection(domain, pipe_name, conn_out); +} /********************************************************************************** **********************************************************************************/ @@ -589,8 +436,7 @@ BOOL cm_check_for_native_mode_win2k( const char *domain ) ZERO_STRUCT( ctr ); - if ( !NT_STATUS_IS_OK(result = cm_open_connection(domain, PI_LSARPC_DS, &conn)) ) - { + if ( !NT_STATUS_IS_OK(result = cm_open_connection(domain, PI_LSARPC_DS, &conn)) ) { 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; @@ -598,18 +444,15 @@ BOOL cm_check_for_native_mode_win2k( const char *domain ) if ( conn.cli ) { if ( !NT_STATUS_IS_OK(cli_ds_getprimarydominfo( conn.cli, - conn.cli->mem_ctx, DsRolePrimaryDomainInfoBasic, &ctr)) ) - { + 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) ) - { + && !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE) ) ret = True; - } done: if ( conn.cli ) @@ -622,7 +465,7 @@ done: /* Return a LSA policy handle on a domain */ -CLI_POLICY_HND *cm_get_lsa_handle(char *domain) +CLI_POLICY_HND *cm_get_lsa_handle(const char *domain) { struct winbindd_cm_conn *conn; uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; @@ -631,9 +474,8 @@ CLI_POLICY_HND *cm_get_lsa_handle(char *domain) /* Look for existing connections */ - if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_LSARPC, &conn))) { + if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_LSARPC, &conn))) return NULL; - } /* This *shitty* code needs scrapping ! JRA */ if (policy_handle_is_valid(&conn->pol)) { @@ -648,9 +490,8 @@ CLI_POLICY_HND *cm_get_lsa_handle(char *domain) 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))) { + if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_LSARPC, &conn))) return NULL; - } result = cli_lsa_open_policy(conn->cli, conn->cli->mem_ctx, False, des_access, &conn->pol); @@ -681,9 +522,8 @@ CLI_POLICY_HND *cm_get_sam_handle(char *domain) /* Look for existing connections */ - if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_SAMR, &conn))) { + if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_SAMR, &conn))) return NULL; - } /* This *shitty* code needs scrapping ! JRA */ if (policy_handle_is_valid(&conn->pol)) { @@ -697,9 +537,8 @@ CLI_POLICY_HND *cm_get_sam_handle(char *domain) 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))) { + if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_SAMR, &conn))) return NULL; - } result = cli_samr_connect(conn->cli, conn->cli->mem_ctx, des_access, &conn->pol); @@ -719,275 +558,67 @@ CLI_POLICY_HND *cm_get_sam_handle(char *domain) return &hnd; } -#if 0 /* This code now *well* out of date */ - -/* Return a SAM domain policy handle on a domain */ +/* 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. */ -CLI_POLICY_HND *cm_get_sam_dom_handle(char *domain, DOM_SID *domain_sid) +NTSTATUS cm_get_netlogon_cli(const char *domain, + const unsigned char *trust_passwd, + uint32 sec_channel_type, + BOOL fresh, + struct cli_state **cli) { - 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; + NTSTATUS result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; + struct winbindd_cm_conn *conn; + fstring lock_name; + BOOL got_mutex; - /* Add to list */ + if (!cli) + return NT_STATUS_INVALID_PARAMETER; - DLIST_ADD(cm_conns, conn); + /* Open an initial conection - keep the mutex. */ - ok: - hnd.pol = conn->pol; - hnd.cli = conn->cli; + find_cm_connection(domain, PIPE_NETLOGON, &conn); - return &hnd; -} + if ( fresh && (conn != NULL) ) { + cli_shutdown(conn->cli); + conn->cli = NULL; -/* Return a SAM policy handle on a domain user */ + conn = NULL; -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; + /* purge connection from cache */ + find_cm_connection(domain, PIPE_NETLOGON, &conn); + if (conn != NULL) { + DEBUG(0,("Could not purge connection\n")); + return NT_STATUS_UNSUCCESSFUL; } } - /* 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 != NULL) { + *cli = conn->cli; + return NT_STATUS_OK; } - 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); + result = new_cm_connection(domain, PIPE_NETLOGON, &conn); 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); + return result; - conn->pipe_data.samr.pipe_type = SAM_PIPE_GROUP; - conn->cli = basic_conn->cli; - conn->pipe_data.samr.rid = group_rid; + snprintf(lock_name, sizeof(lock_name), "NETLOGON\\%s", conn->controller); - 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(char *domain, 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 */ - - if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_NETLOGON, &conn))) { - return result; + if (!(got_mutex = secrets_named_mutex(lock_name, WINBIND_SERVER_MUTEX_WAIT_TIME))) { + DEBUG(0,("cm_get_netlogon_cli: mutex grab failed for %s\n", conn->controller)); } + + result = cli_nt_establish_netlogon(conn->cli, sec_channel_type, trust_passwd); - result = cli_nt_setup_creds(conn->cli, get_sec_chan(), trust_passwd, &neg_flags, 2); - + if (got_mutex) + secrets_named_mutex_release(lock_name); + 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))) { - return result; - } - - /* Try again */ - result = cli_nt_setup_creds( conn->cli, get_sec_chan(),trust_passwd, &neg_flags, 2); - } - - if (!NT_STATUS_IS_OK(result)) { - cli_shutdown(conn->cli); - DLIST_REMOVE(cm_conns, conn); - SAFE_FREE(conn); - return result; - } + cli_shutdown(conn->cli); + DLIST_REMOVE(cm_conns, conn); + SAFE_FREE(conn); + return result; } *cli = conn->cli; @@ -1028,3 +659,34 @@ void winbindd_cm_status(void) else DEBUG(0, ("\tNo active connections\n")); } + +/* Close all cached connections */ + +void winbindd_cm_flush(void) +{ + struct winbindd_cm_conn *conn, tmp; + + /* Flush connection cache */ + + for (conn = cm_conns; conn; conn = conn->next) { + + if (!connection_ok(conn)) + continue; + + DEBUG(10, ("Closing connection to %s on %s\n", + conn->pipe_name, conn->controller)); + + if (conn->cli) + cli_shutdown(conn->cli); + + tmp.next = conn->next; + + DLIST_REMOVE(cm_conns, conn); + SAFE_FREE(conn); + conn = &tmp; + } + + /* Flush failed connection cache */ + + flush_negative_conn_cache(); +}