struct in_addr dest_ip;
fstring remote_machine;
NTSTATUS result;
- uint32 neg_flags = 0x000001ff;
*retry = False;
return NT_STATUS_NO_MEMORY;
}
- result = cli_nt_setup_creds(*cli, sec_chan, trust_passwd, &neg_flags, 2);
+ result = cli_nt_establish_netlogon(*cli, sec_chan, trust_passwd);
if (!NT_STATUS_IS_OK(result)) {
DEBUG(0,("connect_to_domain_password_server: unable to setup the NETLOGON credentials to machine \
*/
nt_status = cli_netlogon_sam_network_logon(cli, mem_ctx,
+ NULL,
user_info->smb_name.str, user_info->domain.str,
user_info->wksta_name.str, chal,
user_info->lm_resp, user_info->nt_resp,
Resolve via "lmhosts" method.
*********************************************************/
-static BOOL resolve_lmhosts(const char *name, int name_type,
- struct in_addr **return_iplist, int *return_count)
+BOOL resolve_lmhosts(const char *name, int name_type,
+ struct in_addr **return_iplist, int *return_count)
{
/*
* "lmhosts" means parse the local lmhosts file.
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;
}
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;
for (conn = cm_conns; conn; conn = conn->next) {
if (strequal(conn->domain, domain) &&
}
}
}
-
- 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);
+}
/**********************************************************************************
**********************************************************************************/
NTSTATUS cm_get_netlogon_cli(const char *domain,
const unsigned char *trust_passwd,
uint32 sec_channel_type,
+ BOOL fresh,
struct cli_state **cli)
{
NTSTATUS result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
struct winbindd_cm_conn *conn;
- uint32 neg_flags = 0x000001ff;
fstring lock_name;
BOOL got_mutex;
/* Open an initial conection - keep the mutex. */
- if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_NETLOGON, &conn)))
+ find_cm_connection(domain, PIPE_NETLOGON, &conn);
+
+ if ( fresh && (conn != NULL) ) {
+ cli_shutdown(conn->cli);
+ conn->cli = NULL;
+
+ conn = NULL;
+
+ /* 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;
+ }
+ }
+
+ if (conn != NULL) {
+ *cli = conn->cli;
+ return NT_STATUS_OK;
+ }
+
+ result = new_cm_connection(domain, PIPE_NETLOGON, &conn);
+
+ if (!NT_STATUS_IS_OK(result))
return result;
snprintf(lock_name, sizeof(lock_name), "NETLOGON\\%s", conn->controller);
DEBUG(0,("cm_get_netlogon_cli: mutex grab failed for %s\n", conn->controller));
}
- result = cli_nt_setup_creds(conn->cli, sec_channel_type, trust_passwd, &neg_flags, 2);
+ result = cli_nt_establish_netlogon(conn->cli, sec_channel_type, trust_passwd);
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;
-
- snprintf(lock_name, sizeof(lock_name), "NETLOGON\\%s", conn->controller);
- 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));
- }
-
- /* Try again */
- result = cli_nt_setup_creds( conn->cli, sec_channel_type,trust_passwd, &neg_flags, 2);
-
- if (got_mutex)
- secrets_named_mutex_release(lock_name);
- }
-
- 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;
the trust account password. */
/* Don't shut this down - it belongs to the connection cache code */
- result = cm_get_netlogon_cli(lp_workgroup(), trust_passwd, sec_channel_type, &cli);
+ result = cm_get_netlogon_cli(lp_workgroup(),
+ trust_passwd, sec_channel_type,
+ True, &cli);
if (!NT_STATUS_IS_OK(result)) {
DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
TALLOC_CTX *mem_ctx = NULL;
DATA_BLOB lm_resp;
DATA_BLOB nt_resp;
+ DOM_CRED ret_creds;
+ int attempts = 0;
/* Ensure null termination */
state->request.data.auth.user[sizeof(state->request.data.auth.user)-1]='\0';
goto done;
}
- ZERO_STRUCT(info3);
+ do {
+ ZERO_STRUCT(info3);
+ ZERO_STRUCT(ret_creds);
- /* Don't shut this down - it belongs to the connection cache code */
- result = cm_get_netlogon_cli(lp_workgroup(), trust_passwd,
- sec_channel_type,
- &cli);
-
- if (!NT_STATUS_IS_OK(result)) {
- DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
- goto done;
- }
-
- result = cli_netlogon_sam_network_logon(cli, mem_ctx,
- name_user, name_domain,
- global_myname(), chal,
- lm_resp, nt_resp,
- &info3);
+ /* Don't shut this down - it belongs to the connection cache code */
+ result = cm_get_netlogon_cli(lp_workgroup(), trust_passwd,
+ sec_channel_type, False, &cli);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
+ goto done;
+ }
+
+ result = cli_netlogon_sam_network_logon(cli, mem_ctx,
+ &ret_creds,
+ name_user, name_domain,
+ global_myname(), chal,
+ lm_resp, nt_resp,
+ &info3);
+ attempts += 1;
+
+ /* We have to try a second time as cm_get_netlogon_cli
+ might not yet have noticed that the DC has killed
+ our connection. */
+
+ } while ( (attempts < 2) && (cli->fd == -1) );
+
+
+ clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), &ret_creds);
uni_group_cache_store_netlogon(mem_ctx, &info3);
done:
const char *domain = NULL;
const char *contact_domain;
const char *workstation;
+ DOM_CRED ret_creds;
+ int attempts = 0;
DATA_BLOB lm_resp, nt_resp;
goto done;
}
- ZERO_STRUCT(info3);
+ do {
+ ZERO_STRUCT(info3);
+ ZERO_STRUCT(ret_creds);
+
+ /* Don't shut this down - it belongs to the connection cache code */
+ result = cm_get_netlogon_cli(contact_domain, trust_passwd,
+ sec_channel_type, False, &cli);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(3, ("could not open handle to NETLOGON pipe (error: %s)\n",
+ nt_errstr(result)));
+ goto done;
+ }
+
+ result = cli_netlogon_sam_network_logon(cli, mem_ctx,
+ &ret_creds,
+ user, domain,
+ workstation,
+ state->request.data.auth_crap.chal,
+ lm_resp, nt_resp,
+ &info3);
+
+ attempts += 1;
- /* Don't shut this down - it belongs to the connection cache code */
- result = cm_get_netlogon_cli(contact_domain, trust_passwd, sec_channel_type, &cli);
+ /* We have to try a second time as cm_get_netlogon_cli
+ might not yet have noticed that the DC has killed
+ our connection. */
- if (!NT_STATUS_IS_OK(result)) {
- DEBUG(3, ("could not open handle to NETLOGON pipe (error: %s)\n", nt_errstr(result)));
- goto done;
- }
+ } while ( (attempts < 2) && (cli->fd == -1) );
- result = cli_netlogon_sam_network_logon(cli, mem_ctx,
- user, domain,
- workstation, state->request.data.auth_crap.chal,
- lm_resp, nt_resp,
- &info3);
+ clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), &ret_creds);
if (NT_STATUS_IS_OK(result)) {
uni_group_cache_store_netlogon(mem_ctx, &info3);
/* Logon domain user */
NTSTATUS cli_netlogon_sam_logon(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ DOM_CRED *ret_creds,
const char *username, const char *password,
int logon_type)
{
ZERO_STRUCT(q);
ZERO_STRUCT(r);
+ ZERO_STRUCT(dummy_rtn_creds);
/* Initialise parse structures */
q.validation_level = validation_level;
- memset(&dummy_rtn_creds, '\0', sizeof(dummy_rtn_creds));
- dummy_rtn_creds.timestamp.time = time(NULL);
+ if (ret_creds == NULL)
+ ret_creds = &dummy_rtn_creds;
ctr.switch_value = logon_type;
}
init_sam_info(&q.sam_id, cli->srv_name_slash, global_myname(),
- &clnt_creds, &dummy_rtn_creds, logon_type,
+ &clnt_creds, ret_creds, logon_type,
&ctr);
/* Marshall data and send request */
/* Return results */
result = r.status;
+ memcpy(ret_creds, &r.srv_creds, sizeof(*ret_creds));
done:
prs_mem_free(&qbuf);
**/
NTSTATUS cli_netlogon_sam_network_logon(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ DOM_CRED *ret_creds,
const char *username, const char *domain, const char *workstation,
const uint8 chal[8],
DATA_BLOB lm_response, DATA_BLOB nt_response,
ZERO_STRUCT(q);
ZERO_STRUCT(r);
+ ZERO_STRUCT(dummy_rtn_creds);
workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
q.validation_level = validation_level;
- memset(&dummy_rtn_creds, '\0', sizeof(dummy_rtn_creds));
- dummy_rtn_creds.timestamp.time = time(NULL);
+ if (ret_creds == NULL)
+ ret_creds = &dummy_rtn_creds;
ctr.switch_value = NET_LOGON_TYPE;
lm_response.data, lm_response.length, nt_response.data, nt_response.length);
init_sam_info(&q.sam_id, cli->srv_name_slash, global_myname(),
- &clnt_creds, &dummy_rtn_creds, NET_LOGON_TYPE,
+ &clnt_creds, ret_creds, NET_LOGON_TYPE,
&ctr);
/* Marshall data and send request */
/* Return results */
result = r.status;
+ memcpy(ret_creds, &r.srv_creds, sizeof(*ret_creds));
done:
prs_mem_free(&qbuf);
Open a session to the NETLOGON pipe using schannel.
****************************************************************************/
-BOOL cli_nt_open_netlogon(struct cli_state *cli, const char *trust_password,
- int sec_chan)
+NTSTATUS cli_nt_establish_netlogon(struct cli_state *cli, int sec_chan,
+ const char *trust_password)
{
NTSTATUS result;
uint32 neg_flags = 0x000001ff;
if (lp_client_schannel() != False)
neg_flags |= NETLOGON_NEG_SCHANNEL;
-
- if (!cli_nt_session_open(cli, PI_NETLOGON)) {
- return False;
- }
-
- if (!secrets_init()) {
- DEBUG(3,("Failed to init secrets.tdb\n"));
- return False;
- }
-
result = cli_nt_setup_creds(cli, sec_chan, trust_password,
&neg_flags, 2);
if (!NT_STATUS_IS_OK(result)) {
cli_nt_session_close(cli);
- return False;
+ return result;
}
if ((lp_client_schannel() == True) &&
DEBUG(3, ("Server did not offer schannel\n"));
cli_nt_session_close(cli);
- return False;
+ return NT_STATUS_UNSUCCESSFUL;
}
if ((lp_client_schannel() == False) ||
((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
- return True;
+ return NT_STATUS_OK;
}
/* Server offered schannel, so try it. */
"Error was %s\n",
PIPE_NETLOGON, cli->desthost,
cli_errstr(cli)));
- return False;
+ return NT_STATUS_UNSUCCESSFUL;
}
cli->nt_pipe_fnum = (uint16)fnum;
"Error was %s\n",
PIPE_NETLOGON, cli->desthost,
cli_errstr(cli)));
- return False;
+ return NT_STATUS_UNSUCCESSFUL;
}
cli->nt_pipe_fnum = (uint16)fnum;
DEBUG(0,("Pipe hnd state failed. Error was %s\n",
cli_errstr(cli)));
cli_close(cli, cli->nt_pipe_fnum);
- return False;
+ return NT_STATUS_UNSUCCESSFUL;
}
}
if (!rpc_pipe_bind(cli, PI_NETLOGON, global_myname(), True)) {
DEBUG(2,("rpc bind to %s failed\n", PIPE_NETLOGON));
cli_close(cli, cli->nt_pipe_fnum);
- return False;
+ return NT_STATUS_UNSUCCESSFUL;
}
- return True;
+ return NT_STATUS_OK;
}
const char *username, *password;
uint32 neg_flags = 0x000001ff;
int auth_level = 2;
+ DOM_CRED ret_creds;
/* Check arguments */
/* Perform the sam logon */
- result = cli_netlogon_sam_logon(cli, mem_ctx, username, password, logon_type);
+ ZERO_STRUCT(ret_creds);
+
+ result = cli_netlogon_sam_logon(cli, mem_ctx, &ret_creds, username, password, logon_type);
+
+ clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), &ret_creds);
+
+ result = cli_netlogon_sam_logon(cli, mem_ctx, &ret_creds, username, password, logon_type);
if (!NT_STATUS_IS_OK(result))
goto done;
/* Open pipe */
+ if (cmd_entry->pipe_idx != -1) {
+ if (!cli_nt_session_open(cli, cmd_entry->pipe_idx)) {
+ DEBUG(0, ("Could not initialise %s\n",
+ get_pipe_name_from_index(cmd_entry->pipe_idx)));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ }
+
if (cmd_entry->pipe_idx == PI_NETLOGON) {
uchar trust_password[16];
uint32 sec_channel_type;
return NT_STATUS_UNSUCCESSFUL;
}
- if (!cli_nt_open_netlogon(cli, trust_password,
- sec_channel_type)) {
+ if (!NT_STATUS_IS_OK(cli_nt_establish_netlogon(cli, sec_channel_type,
+ trust_password))) {
DEBUG(0, ("Could not initialise NETLOGON pipe\n"));
return NT_STATUS_UNSUCCESSFUL;
}
- } else {
- if (cmd_entry->pipe_idx != -1) {
- if (!cli_nt_session_open(cli, cmd_entry->pipe_idx)) {
- DEBUG(0, ("Could not initialise %s\n",
- get_pipe_name_from_index(cmd_entry->pipe_idx)));
- return NT_STATUS_UNSUCCESSFUL;
- }
- }
}
/* Run command */
fstrcpy(cli->domain, lp_workgroup());
+ if (!cli_nt_session_open(cli, PI_NETLOGON)) {
+ DEBUG(0,("Could not open connection to NETLOGON pipe\n"));
+ goto fail;
+ }
+
if (!secrets_fetch_trust_account_password(lp_workgroup(),
trust_password,
NULL, &sec_channel)) {
goto fail;
}
- if (!cli_nt_open_netlogon(cli, trust_password, sec_channel)) {
+ if (!NT_STATUS_IS_OK(cli_nt_establish_netlogon(cli, sec_channel,
+ trust_password))) {
DEBUG(0,("Error connecting to NETLOGON pipe\n"));
goto fail;
}