Пример #1
0
NTSTATUS rpccli_setup_netlogon_creds_locked(
	struct cli_state *cli,
	enum dcerpc_transport_t transport,
	struct netlogon_creds_cli_context *creds_ctx,
	bool force_reauth,
	struct cli_credentials *cli_creds,
	uint32_t *negotiate_flags)
{
	TALLOC_CTX *frame = talloc_stackframe();
	struct rpc_pipe_client *netlogon_pipe = NULL;
	struct netlogon_creds_CredentialState *creds = NULL;
	uint8_t num_nt_hashes = 0;
	const struct samr_Password *nt_hashes[2] = { NULL, NULL };
	uint8_t idx_nt_hashes = 0;
	NTSTATUS status;

	status = netlogon_creds_cli_get(creds_ctx, frame, &creds);
	if (NT_STATUS_IS_OK(status)) {
		const char *action = "using";

		if (force_reauth) {
			action = "overwrite";
		}

		DEBUG(5,("%s: %s cached netlogon_creds cli[%s/%s] to %s\n",
			 __FUNCTION__, action,
			 creds->account_name, creds->computer_name,
			 smbXcli_conn_remote_name(cli->conn)));
		if (!force_reauth) {
			goto done;
		}
		TALLOC_FREE(creds);
	}

	nt_hashes[0] = cli_credentials_get_nt_hash(cli_creds, talloc_tos());
	if (nt_hashes[0] == NULL) {
		TALLOC_FREE(frame);
		return NT_STATUS_NO_MEMORY;
	}
	num_nt_hashes = 1;

	nt_hashes[1] = cli_credentials_get_old_nt_hash(cli_creds,
						       talloc_tos());
	if (nt_hashes[1] != NULL) {
		num_nt_hashes = 2;
	}

	status = cli_rpc_pipe_open_noauth_transport(cli,
						    transport,
						    &ndr_table_netlogon,
						    &netlogon_pipe);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(5,("%s: failed to open noauth netlogon connection to %s - %s\n",
			 __FUNCTION__,
			 smbXcli_conn_remote_name(cli->conn),
			 nt_errstr(status)));
		TALLOC_FREE(frame);
		return status;
	}
	talloc_steal(frame, netlogon_pipe);

	status = netlogon_creds_cli_auth(creds_ctx,
					 netlogon_pipe->binding_handle,
					 num_nt_hashes,
					 nt_hashes,
					 &idx_nt_hashes);
	if (!NT_STATUS_IS_OK(status)) {
		TALLOC_FREE(frame);
		return status;
	}

	status = netlogon_creds_cli_get(creds_ctx, frame, &creds);
	if (!NT_STATUS_IS_OK(status)) {
		TALLOC_FREE(frame);
		return NT_STATUS_INTERNAL_ERROR;
	}

	DEBUG(5,("%s: using new netlogon_creds cli[%s/%s] to %s\n",
		 __FUNCTION__,
		 creds->account_name, creds->computer_name,
		 smbXcli_conn_remote_name(cli->conn)));

done:
	if (negotiate_flags != NULL) {
		*negotiate_flags = creds->negotiate_flags;
	}

	TALLOC_FREE(frame);
	return NT_STATUS_OK;
}
Пример #2
0
NTSTATUS rpccli_connect_netlogon(
	struct cli_state *cli,
	enum dcerpc_transport_t transport,
	struct netlogon_creds_cli_context *creds_ctx,
	bool force_reauth,
	struct cli_credentials *trust_creds,
	struct rpc_pipe_client **_rpccli)
{
	TALLOC_CTX *frame = talloc_stackframe();
	struct netlogon_creds_CredentialState *creds = NULL;
	enum netlogon_creds_cli_lck_type lck_type;
	enum netr_SchannelType sec_chan_type;
	struct netlogon_creds_cli_lck *lck = NULL;
	uint32_t negotiate_flags;
	uint8_t found_session_key[16] = {0};
	bool found_existing_creds = false;
	bool do_serverauth;
	struct rpc_pipe_client *rpccli;
	NTSTATUS status;
	bool retry = false;

	sec_chan_type = cli_credentials_get_secure_channel_type(trust_creds);
	if (sec_chan_type == SEC_CHAN_NULL) {
		DBG_ERR("secure_channel_type gave SEC_CHAN_NULL\n");
		status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
		goto fail;
	}

again:

	/*
	 * See whether we can use existing netlogon_creds or
	 * whether we have to serverauthenticate.
	 */
	status = netlogon_creds_cli_get(creds_ctx, frame, &creds);

	if (NT_STATUS_IS_OK(status)) {
		int cmp = memcmp(found_session_key,
				 creds->session_key,
				 sizeof(found_session_key));
		found_existing_creds = (cmp != 0);

		memcpy(found_session_key,
		       creds->session_key,
		       sizeof(found_session_key));

		TALLOC_FREE(creds);
	}

	lck_type = (force_reauth || !found_existing_creds) ?
		NETLOGON_CREDS_CLI_LCK_EXCLUSIVE :
		NETLOGON_CREDS_CLI_LCK_SHARED;

	status = netlogon_creds_cli_lck(creds_ctx, lck_type, frame, &lck);
	if (!NT_STATUS_IS_OK(status)) {
		DBG_DEBUG("netlogon_creds_cli_lck failed: %s\n",
			  nt_errstr(status));
		goto fail;
	}

	if (!found_existing_creds) {
		/*
		 * Try to find creds under the lock again. Someone
		 * else might have done it for us.
		 */
		status = netlogon_creds_cli_get(creds_ctx, frame, &creds);

		if (NT_STATUS_IS_OK(status)) {
			int cmp = memcmp(found_session_key,
					 creds->session_key,
					 sizeof(found_session_key));
			found_existing_creds = (cmp != 0);

			memcpy(found_session_key, creds->session_key,
			       sizeof(found_session_key));

			TALLOC_FREE(creds);
		}
	}

	do_serverauth = force_reauth || !found_existing_creds;

	if (!do_serverauth) {
		/*
		 * Do the quick schannel bind without a reauth
		 */
		status = cli_rpc_pipe_open_bind_schannel(
			cli, &ndr_table_netlogon, transport, creds_ctx,
			&rpccli);
		if (!retry && NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
			DBG_DEBUG("Retrying with serverauthenticate\n");
			TALLOC_FREE(lck);
			retry = true;
			goto again;
		}
		if (!NT_STATUS_IS_OK(status)) {
			DBG_DEBUG("cli_rpc_pipe_open_bind_schannel "
				  "failed: %s\n", nt_errstr(status));
			goto fail;
		}
		goto done;
	}

	if (cli_credentials_is_anonymous(trust_creds)) {
		DBG_WARNING("get_trust_credential for %s only gave anonymous,"
			    "unable to negotiate NETLOGON credentials\n",
			    netlogon_creds_cli_debug_string(
				    creds_ctx, frame));
		status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
		goto fail;
	}

	status = rpccli_setup_netlogon_creds_locked(
		cli, transport, creds_ctx, true, trust_creds,
		&negotiate_flags);
	if (!NT_STATUS_IS_OK(status)) {
		DBG_DEBUG("rpccli_setup_netlogon_creds failed for %s, "
			  "unable to setup NETLOGON credentials: %s\n",
			  netlogon_creds_cli_debug_string(
				  creds_ctx, frame),
			  nt_errstr(status));
		goto fail;
	}

	if (!(negotiate_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) {
		if (lp_winbind_sealed_pipes() || lp_require_strong_key()) {
			status = NT_STATUS_DOWNGRADE_DETECTED;
			DBG_WARNING("Unwilling to make connection to %s"
				    "without connection level security, "
				    "must set 'winbind sealed pipes = false'"
				    " and 'require strong key = false' "
				    "to proceed: %s\n",
				    netlogon_creds_cli_debug_string(
					    creds_ctx, frame),
				    nt_errstr(status));
			goto fail;
		}

		status = cli_rpc_pipe_open_noauth_transport(
			cli, transport, &ndr_table_netlogon, &rpccli);
		if (!NT_STATUS_IS_OK(status)) {
			DBG_DEBUG("cli_rpc_pipe_open_noauth_transport "
				  "failed: %s\n", nt_errstr(status));
			goto fail;
		}
		goto done;
	}

	status = cli_rpc_pipe_open_bind_schannel(
		cli, &ndr_table_netlogon, transport, creds_ctx, &rpccli);
	if (!NT_STATUS_IS_OK(status)) {
		DBG_DEBUG("cli_rpc_pipe_open_bind_schannel "
			  "failed: %s\n", nt_errstr(status));
		goto fail;
	}

	status = netlogon_creds_cli_check(creds_ctx, rpccli->binding_handle,
					  NULL);
	if (!NT_STATUS_IS_OK(status)) {
		DBG_WARNING("netlogon_creds_cli_check failed: %s\n",
			    nt_errstr(status));
		goto fail;
	}

done:
	*_rpccli = rpccli;
	status = NT_STATUS_OK;
fail:
	ZERO_STRUCT(found_session_key);
	TALLOC_FREE(lck);
	TALLOC_FREE(frame);
	return status;
}
Пример #3
0
NTSTATUS rpccli_setup_netlogon_creds(struct cli_state *cli,
				     enum dcerpc_transport_t transport,
				     struct netlogon_creds_cli_context *netlogon_creds,
				     bool force_reauth,
				     struct samr_Password current_nt_hash,
				     const struct samr_Password *previous_nt_hash)
{
	TALLOC_CTX *frame = talloc_stackframe();
	struct rpc_pipe_client *netlogon_pipe = NULL;
	struct netlogon_creds_CredentialState *creds = NULL;
	NTSTATUS status;

	status = netlogon_creds_cli_get(netlogon_creds,
					frame, &creds);
	if (NT_STATUS_IS_OK(status)) {
		const char *action = "using";

		if (force_reauth) {
			action = "overwrite";
		}

		DEBUG(5,("%s: %s cached netlogon_creds cli[%s/%s] to %s\n",
			 __FUNCTION__, action,
			 creds->account_name, creds->computer_name,
			 smbXcli_conn_remote_name(cli->conn)));
		if (!force_reauth) {
			TALLOC_FREE(frame);
			return NT_STATUS_OK;
		}
		TALLOC_FREE(creds);
	}

	status = cli_rpc_pipe_open_noauth_transport(cli,
						    transport,
						    &ndr_table_netlogon,
						    &netlogon_pipe);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(5,("%s: failed to open noauth netlogon connection to %s - %s\n",
			 __FUNCTION__,
			 smbXcli_conn_remote_name(cli->conn),
			 nt_errstr(status)));
		TALLOC_FREE(frame);
		return status;
	}
	talloc_steal(frame, netlogon_pipe);

	status = netlogon_creds_cli_auth(netlogon_creds,
					 netlogon_pipe->binding_handle,
					 current_nt_hash,
					 previous_nt_hash);
	if (!NT_STATUS_IS_OK(status)) {
		TALLOC_FREE(frame);
		return status;
	}

	status = netlogon_creds_cli_get(netlogon_creds,
					frame, &creds);
	if (!NT_STATUS_IS_OK(status)) {
		TALLOC_FREE(frame);
		return NT_STATUS_INTERNAL_ERROR;
	}

	DEBUG(5,("%s: using new netlogon_creds cli[%s/%s] to %s\n",
		 __FUNCTION__,
		 creds->account_name, creds->computer_name,
		 smbXcli_conn_remote_name(cli->conn)));

	TALLOC_FREE(frame);
	return NT_STATUS_OK;
}