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; } }
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; }