From 6b2eb72df0bcf9143d013e64410ebde78d57b1c4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 16 Jan 2003 20:08:26 +0000 Subject: Fixed up mutex protection around winbindd logon code. Sync with APP-HEAD. Jeremy. (This used to be commit daf179bcd6297b525bfc644efb154734723f4d58) --- source3/nsswitch/winbindd_cm.c | 69 +++++++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 28 deletions(-) (limited to 'source3/nsswitch') diff --git a/source3/nsswitch/winbindd_cm.c b/source3/nsswitch/winbindd_cm.c index 1105c77572..54096c0c1d 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; }; @@ -301,7 +302,7 @@ static void add_failed_connection_entry(struct winbindd_cm_conn *new_conn, /* 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 winbindd_cm_conn *new_conn, BOOL keep_mutex) { struct failed_connection_cache *fcc; NTSTATUS result; @@ -309,6 +310,7 @@ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index, struct in_addr dc_ip; int i; BOOL retry = True; + BOOL got_mutex = False; ZERO_STRUCT(dc_ip); @@ -365,12 +367,23 @@ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index, 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, global_myname(), 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); @@ -378,6 +391,8 @@ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index, 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; } @@ -392,12 +407,16 @@ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index, * 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; } @@ -435,7 +454,8 @@ static BOOL connection_ok(struct winbindd_cm_conn *conn) /* 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) +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; @@ -452,6 +472,12 @@ static NTSTATUS get_connection_from_cache(const char *domain, const char *pipe_n 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; } } @@ -463,7 +489,7 @@ static NTSTATUS get_connection_from_cache(const char *domain, const char *pipe_n ZERO_STRUCTP(conn); - if (!NT_STATUS_IS_OK(result = cm_open_connection(domain, get_pipe_index(pipe_name), 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); @@ -491,7 +517,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, 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; @@ -529,7 +555,7 @@ CLI_POLICY_HND *cm_get_lsa_handle(const 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, False))) return NULL; /* This *shitty* code needs scrapping ! JRA */ @@ -545,7 +571,7 @@ CLI_POLICY_HND *cm_get_lsa_handle(const 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, False))) return NULL; result = cli_lsa_open_policy(conn->cli, conn->cli->mem_ctx, False, @@ -577,7 +603,7 @@ 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, False))) return NULL; /* This *shitty* code needs scrapping ! JRA */ @@ -592,7 +618,7 @@ 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, False))) return NULL; result = cli_samr_connect(conn->cli, conn->cli->mem_ctx, @@ -849,28 +875,19 @@ NTSTATUS cm_get_netlogon_cli(const char *domain, const unsigned char *trust_pass NTSTATUS result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; struct winbindd_cm_conn *conn; uint32 neg_flags = 0x000001ff; - fstring srv_name; - struct in_addr dc_ip; if (!cli) return NT_STATUS_INVALID_PARAMETER; - if (!cm_get_dc_name(domain, srv_name, &dc_ip)) - return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; + /* Open an initial conection - keep the mutex. */ - if (!secrets_named_mutex(srv_name, 10)) { - DEBUG(0,("cm_get_netlogon_cli: mutex grab failed for %s\n", srv_name)); - return NT_STATUS_POSSIBLE_DEADLOCK; - } - - /* Open an initial conection */ - - if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_NETLOGON, &conn))) + 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); - secrets_named_mutex_release(srv_name); + 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", @@ -879,18 +896,14 @@ NTSTATUS cm_get_netlogon_cli(const char *domain, const unsigned char *trust_pass /* Hit the cache code again. This cleans out the old connection and gets a new one */ if (conn->cli->fd == -1) { - if (!secrets_named_mutex(srv_name, 10)) { - DEBUG(0,("cm_get_netlogon_cli: mutex grab failed for %s\n", srv_name)); - return NT_STATUS_POSSIBLE_DEADLOCK; - } - - if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_NETLOGON, &conn))) + 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); - secrets_named_mutex_release(srv_name); + if (conn->mutex_ref_count) + secrets_named_mutex_release(conn->controller, &conn->mutex_ref_count); } if (!NT_STATUS_IS_OK(result)) { -- cgit