static void init_domain_recv_queryinfo(struct tevent_req *subreq)
{
	struct init_domain_state *state =
		tevent_req_callback_data(subreq,
		struct init_domain_state);
	struct lsa_DomainInfo *dominfo;
	struct composite_context *ctx;
	uint32_t lflags;

	state->ctx->status = dcerpc_lsa_QueryInfoPolicy_r_recv(subreq, state);
	TALLOC_FREE(subreq);
	if (!composite_is_ok(state->ctx)) return;
	state->ctx->status = state->queryinfo.out.result;
	if (!composite_is_ok(state->ctx)) return;

	if (!dom_sid_equal(state->domain->info->sid, &global_sid_Builtin)) {
		dominfo = &(*state->queryinfo.out.info)->account_domain;
		
		if (strcasecmp(state->domain->info->name, dominfo->name.string) != 0) {
			DEBUG(2, ("Expected domain name %s, DC %s said %s\n",
				  state->domain->info->name,
				  dcerpc_server_name(state->domain->libnet_ctx->lsa.pipe),
				  dominfo->name.string));
			composite_error(state->ctx, NT_STATUS_INVALID_DOMAIN_STATE);
			return;
		}
		
		if (!dom_sid_equal(state->domain->info->sid, dominfo->sid)) {
			DEBUG(2, ("Expected domain sid %s, DC %s said %s\n",
				  dom_sid_string(state, state->domain->info->sid),
				  dcerpc_server_name(state->domain->libnet_ctx->lsa.pipe),
				  dom_sid_string(state, dominfo->sid)));
			composite_error(state->ctx, NT_STATUS_INVALID_DOMAIN_STATE);
			return;
		}
	}

	state->domain->samr_binding = init_domain_binding(state, &ndr_table_samr);

	/* We want to use the same flags as the LSA pipe did (so, if
	 * it needed schannel, then we need that here too) */
	lflags = dcerpc_binding_get_flags(state->domain->lsa_binding);
	state->ctx->status = dcerpc_binding_set_flags(state->domain->samr_binding,
						      lflags, 0);
	if (!composite_is_ok(state->ctx)) return;

	state->domain->libnet_ctx->samr.pipe = NULL;
	state->domain->libnet_ctx->samr.samr_handle = NULL;

	ctx = wb_connect_samr_send(state, state->domain);
	composite_continue(state->ctx, ctx, init_domain_recv_samr, state);
}
static bool retry_with_schannel(struct init_domain_state *state, 
				struct dcerpc_binding *binding,
				const struct ndr_interface_table *table,
				void (*continuation)(struct composite_context *))
{
	struct composite_context *ctx;
	uint32_t nflags;
	uint32_t bflags;

	state->ctx->status = NT_STATUS_OK;

	nflags = dcerpc_binding_get_flags(state->domain->netlogon_binding);
	bflags = dcerpc_binding_get_flags(binding);

	if ((nflags & DCERPC_SCHANNEL) && !(bflags & DCERPC_SCHANNEL)) {
		/* Opening a policy handle failed, perhaps it was
		 * because we don't get a 'wrong password' error on
		 * NTLMSSP binds */

		/* Try again with schannel */
		bflags |= DCERPC_SCHANNEL | DCERPC_SCHANNEL_AUTO;

		state->ctx->status = dcerpc_binding_set_flags(binding, bflags, 0);
		if (!composite_is_ok(state->ctx)) return true;

		/* Try again, likewise on the same IPC$ share, 
		   secured with SCHANNEL */
		ctx = dcerpc_secondary_auth_connection_send(state->domain->netlogon_pipe,
							    binding,
							    table, 
							    state->domain->libnet_ctx->cred,
							    state->domain->libnet_ctx->lp_ctx);
		composite_continue(state->ctx, ctx, continuation, state);		
		return true;
	} else {
		return false;
	}
}
Beispiel #3
0
static NTSTATUS remote_op_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *iface, uint32_t if_version)
{
        NTSTATUS status;
	const struct ndr_interface_table *table;
	struct dcesrv_remote_private *priv;
	const char *binding = lpcfg_parm_string(dce_call->conn->dce_ctx->lp_ctx, NULL, "dcerpc_remote", "binding");
	const char *user, *pass, *domain;
	struct cli_credentials *credentials;
	bool must_free_credentials = true;
	bool machine_account;
	struct dcerpc_binding		*b;
	struct composite_context	*pipe_conn_req;
	uint32_t flags = 0;

	machine_account = lpcfg_parm_bool(dce_call->conn->dce_ctx->lp_ctx, NULL, "dcerpc_remote", "use_machine_account", false);

	priv = talloc(dce_call->conn, struct dcesrv_remote_private);
	if (!priv) {
		return NT_STATUS_NO_MEMORY;	
	}
	
	priv->c_pipe = NULL;
	dce_call->context->private_data = priv;

	if (!binding) {
		DEBUG(0,("You must specify a DCE/RPC binding string\n"));
		return NT_STATUS_INVALID_PARAMETER;
	}

	user = lpcfg_parm_string(dce_call->conn->dce_ctx->lp_ctx, NULL, "dcerpc_remote", "user");
	pass = lpcfg_parm_string(dce_call->conn->dce_ctx->lp_ctx, NULL, "dcerpc_remote", "password");
	domain = lpcfg_parm_string(dce_call->conn->dce_ctx->lp_ctx, NULL, "dceprc_remote", "domain");

	table = ndr_table_by_syntax(&iface->syntax_id);
	if (!table) {
		dce_call->fault_code = DCERPC_NCA_S_UNKNOWN_IF;
		return NT_STATUS_NET_WRITE_FAULT;
	}

	if (user && pass) {
		DEBUG(5, ("dcerpc_remote: RPC Proxy: Using specified account\n"));
		credentials = cli_credentials_init(priv);
		if (!credentials) {
			return NT_STATUS_NO_MEMORY;
		}
		cli_credentials_set_conf(credentials, dce_call->conn->dce_ctx->lp_ctx);
		cli_credentials_set_username(credentials, user, CRED_SPECIFIED);
		if (domain) {
			cli_credentials_set_domain(credentials, domain, CRED_SPECIFIED);
		}
		cli_credentials_set_password(credentials, pass, CRED_SPECIFIED);
	} else if (machine_account) {
		DEBUG(5, ("dcerpc_remote: RPC Proxy: Using machine account\n"));
		credentials = cli_credentials_init(priv);
		cli_credentials_set_conf(credentials, dce_call->conn->dce_ctx->lp_ctx);
		if (domain) {
			cli_credentials_set_domain(credentials, domain, CRED_SPECIFIED);
		}
		status = cli_credentials_set_machine_account(credentials, dce_call->conn->dce_ctx->lp_ctx);
		if (!NT_STATUS_IS_OK(status)) {
			return status;
		}
	} else if (dce_call->conn->auth_state.session_info->credentials) {
		DEBUG(5, ("dcerpc_remote: RPC Proxy: Using delegated credentials\n"));
		credentials = dce_call->conn->auth_state.session_info->credentials;
		must_free_credentials = false;
	} else {
		DEBUG(1,("dcerpc_remote: RPC Proxy: You must supply binding, user and password or have delegated credentials\n"));
		return NT_STATUS_INVALID_PARAMETER;
	}

	/* parse binding string to the structure */
	status = dcerpc_parse_binding(dce_call->context, binding, &b);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("Failed to parse dcerpc binding '%s'\n", binding));
		return status;
	}

	/* If we already have a remote association group ID, then use that */
	if (dce_call->conn->assoc_group->proxied_id != 0) {
		status = dcerpc_binding_set_assoc_group_id(b,
			dce_call->conn->assoc_group->proxied_id);
		if (!NT_STATUS_IS_OK(status)) {
			DEBUG(0, ("dcerpc_binding_set_assoc_group_id() - %s'\n",
				  nt_errstr(status)));
			return status;
		}
	}

	status = dcerpc_binding_set_abstract_syntax(b, &iface->syntax_id);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("dcerpc_binding_set_abstract_syntax() - %s'\n",
			  nt_errstr(status)));
		return status;
	}

	if (dce_call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) {
		status = dcerpc_binding_set_flags(b, DCERPC_CONCURRENT_MULTIPLEX, 0);
		if (!NT_STATUS_IS_OK(status)) {
			DEBUG(0, ("dcerpc_binding_set_flags(CONC_MPX) - %s'\n",
				  nt_errstr(status)));
			return status;
		}
	}

	DEBUG(3, ("Using binding %s\n", dcerpc_binding_string(dce_call->context, b)));

	pipe_conn_req = dcerpc_pipe_connect_b_send(dce_call->context, b, table,
						   credentials, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx);
	status = dcerpc_pipe_connect_b_recv(pipe_conn_req, dce_call->context, &(priv->c_pipe));
	
	if (must_free_credentials) {
		talloc_free(credentials);
	}

	if (!NT_STATUS_IS_OK(status)) {
		return status;
	}

	flags = dcerpc_binding_get_flags(priv->c_pipe->binding);
	if (!(flags & DCERPC_CONCURRENT_MULTIPLEX)) {
		dce_call->state_flags &= ~DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
	}

	if (dce_call->conn->assoc_group->proxied_id == 0) {
		dce_call->conn->assoc_group->proxied_id =
			dcerpc_binding_get_assoc_group_id(priv->c_pipe->binding);
	}

	if (!NT_STATUS_IS_OK(status)) {
		return status;
	}

	return NT_STATUS_OK;	
}