static NTSTATUS pipe_cm_find(struct client_ipc_connection *ipc, const struct ndr_syntax_id *interface, struct rpc_pipe_client **presult) { struct client_pipe_connection *p; for (p = ipc->pipe_connections; p; p = p->next) { const char *ipc_remote_name; if (!rpc_pipe_np_smb_conn(p->pipe)) { return NT_STATUS_PIPE_EMPTY; } ipc_remote_name = cli_state_remote_name(ipc->cli); if (strequal(ipc_remote_name, p->pipe->desthost) && ndr_syntax_id_equal(&p->pipe->abstract_syntax, interface)) { *presult = p->pipe; return NT_STATUS_OK; } } return NT_STATUS_PIPE_NOT_AVAILABLE; }
bool init_pipe_handle_list(pipes_struct *p, const struct ndr_syntax_id *syntax) { pipes_struct *plist; struct handle_list *hl; for (plist = get_first_internal_pipe(); plist; plist = get_next_internal_pipe(plist)) { if (ndr_syntax_id_equal(syntax, &plist->syntax)) { break; } if (is_samr_lsa_pipe(&plist->syntax) && is_samr_lsa_pipe(syntax)) { /* * samr and lsa share a handle space (same process * under Windows?) */ break; } } if (plist != NULL) { hl = plist->pipe_handles; if (hl == NULL) { return false; } } else { /* * First open, we have to create the handle list */ hl = SMB_MALLOC_P(struct handle_list); if (hl == NULL) { return false; } ZERO_STRUCTP(hl); DEBUG(10,("init_pipe_handles: created handle list for " "pipe %s\n", get_pipe_name_from_syntax(talloc_tos(), syntax))); } /* * One more pipe is using this list. */ hl->pipe_ref_count++; /* * Point this pipe at this list. */ p->pipe_handles = hl; DEBUG(10,("init_pipe_handles: pipe_handles ref count = %lu for pipe %s\n", (unsigned long)p->pipe_handles->pipe_ref_count, get_pipe_name_from_syntax(talloc_tos(), syntax))); return True; }
static bool check_bind_req(struct pipes_struct *p, struct ndr_syntax_id* abstract, struct ndr_syntax_id* transfer, uint32_t context_id) { struct pipe_rpc_fns *context_fns; bool ok; DEBUG(3,("check_bind_req for %s\n", ndr_interface_name(&abstract->uuid, abstract->if_version))); /* we have to check all now since win2k introduced a new UUID on the lsaprpc pipe */ if (rpc_srv_pipe_exists_by_id(abstract) && ndr_syntax_id_equal(transfer, &ndr_transfer_syntax_ndr)) { DEBUG(3, ("check_bind_req: %s -> %s rpc service\n", rpc_srv_get_pipe_cli_name(abstract), rpc_srv_get_pipe_srv_name(abstract))); } else { return false; } ok = init_pipe_handles(p, abstract); if (!ok) { DEBUG(1, ("Failed to init pipe handles!\n")); return false; } context_fns = talloc(p, struct pipe_rpc_fns); if (context_fns == NULL) { DEBUG(0,("check_bind_req: talloc() failed!\n")); return false; } context_fns->next = context_fns->prev = NULL; context_fns->n_cmds = rpc_srv_get_pipe_num_cmds(abstract); context_fns->cmds = rpc_srv_get_pipe_cmds(abstract); context_fns->context_id = context_id; context_fns->syntax = *abstract; /* add to the list of open contexts */ DLIST_ADD( p->contexts, context_fns ); return True; }
static NTSTATUS pipe_cm_find(struct cli_state *cli, const struct ndr_syntax_id *interface, struct rpc_pipe_client **presult) { struct client_pipe_connection *p; for (p = pipe_connections; p; p = p->next) { if (!rpc_pipe_np_smb_conn(p->pipe)) { return NT_STATUS_PIPE_EMPTY; } if (strequal(cli->desthost, p->pipe->desthost) && ndr_syntax_id_equal(&p->pipe->abstract_syntax, interface)) { *presult = p->pipe; return NT_STATUS_OK; } } return NT_STATUS_PIPE_NOT_AVAILABLE; }
_PUBLIC_ NTSTATUS dcerpc_binding_set_abstract_syntax(struct dcerpc_binding *b, const struct ndr_syntax_id *syntax) { NTSTATUS status; char *s = NULL; if (syntax == NULL) { status = dcerpc_binding_set_string_option(b, "abstract_syntax", NULL); if (!NT_STATUS_IS_OK(status)) { return status; } return NT_STATUS_OK; } if (ndr_syntax_id_equal(&ndr_syntax_id_null, syntax)) { status = dcerpc_binding_set_string_option(b, "abstract_syntax", NULL); if (!NT_STATUS_IS_OK(status)) { return status; } return NT_STATUS_OK; } s = ndr_syntax_id_to_string(b, syntax); if (s == NULL) { return NT_STATUS_NO_MEMORY; } status = dcerpc_binding_set_string_option(b, "abstract_syntax", s); TALLOC_FREE(s); if (!NT_STATUS_IS_OK(status)) { return status; } return NT_STATUS_OK; }
static bool is_samr_lsa_pipe(const struct ndr_syntax_id *syntax) { return (ndr_syntax_id_equal(syntax, &ndr_table_samr.syntax_id) || ndr_syntax_id_equal(syntax, &ndr_table_lsarpc.syntax_id)); }
bool init_pipe_handles(struct pipes_struct *p, const struct ndr_syntax_id *syntax) { struct pipes_struct *plist; struct handle_list *hl; for (plist = InternalPipes; plist; plist = plist->next) { struct pipe_rpc_fns *p_ctx; bool stop = false; for (p_ctx = plist->contexts; p_ctx != NULL; p_ctx = p_ctx->next) { if (ndr_syntax_id_equal(syntax, &p_ctx->syntax)) { stop = true; break; } if (is_samr_lsa_pipe(&p_ctx->syntax) && is_samr_lsa_pipe(syntax)) { /* * samr and lsa share a handle space (same process * under Windows?) */ stop = true; break; } } if (stop) { break; } } if (plist != NULL) { hl = plist->pipe_handles; if (hl == NULL) { return false; } } else { /* * First open, we have to create the handle list */ hl = talloc_zero(NULL, struct handle_list); if (hl == NULL) { return false; } DEBUG(10,("init_pipe_handle_list: created handle list for " "pipe %s\n", get_pipe_name_from_syntax(talloc_tos(), syntax))); } /* * One more pipe is using this list. */ hl->pipe_ref_count++; /* * Point this pipe at this list. */ p->pipe_handles = hl; DEBUG(10,("init_pipe_handle_list: pipe_handles ref count = %lu for " "pipe %s\n", (unsigned long)p->pipe_handles->pipe_ref_count, get_pipe_name_from_syntax(talloc_tos(), syntax))); return True; }
NTSTATUS rpccli_netlogon_setup_creds(struct rpc_pipe_client *cli, const char *server_name, const char *domain, const char *clnt_name, const char *machine_account, const unsigned char machine_pwd[16], enum netr_SchannelType sec_chan_type, uint32_t *neg_flags_inout) { NTSTATUS status; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; struct netr_Credential clnt_chal_send; struct netr_Credential srv_chal_recv; struct samr_Password password; bool retried = false; fstring mach_acct; uint32_t neg_flags = *neg_flags_inout; struct dcerpc_binding_handle *b = cli->binding_handle; if (!ndr_syntax_id_equal(&cli->abstract_syntax, &ndr_table_netlogon.syntax_id)) { return NT_STATUS_INVALID_PARAMETER; } TALLOC_FREE(cli->dc); /* Store the machine account password we're going to use. */ memcpy(password.hash, machine_pwd, 16); fstr_sprintf( mach_acct, "%s$", machine_account); again: /* Create the client challenge. */ generate_random_buffer(clnt_chal_send.data, 8); /* Get the server challenge. */ status = dcerpc_netr_ServerReqChallenge(b, talloc_tos(), cli->srv_name_slash, clnt_name, &clnt_chal_send, &srv_chal_recv, &result); if (!NT_STATUS_IS_OK(status)) { return status; } if (!NT_STATUS_IS_OK(result)) { return result; } /* Calculate the session key and client credentials */ cli->dc = netlogon_creds_client_init(cli, mach_acct, clnt_name, &clnt_chal_send, &srv_chal_recv, &password, &clnt_chal_send, neg_flags); if (!cli->dc) { return NT_STATUS_NO_MEMORY; } /* * Send client auth-2 challenge and receive server repy. */ status = dcerpc_netr_ServerAuthenticate2(b, talloc_tos(), cli->srv_name_slash, cli->dc->account_name, sec_chan_type, cli->dc->computer_name, &clnt_chal_send, /* input. */ &srv_chal_recv, /* output. */ &neg_flags, &result); if (!NT_STATUS_IS_OK(status)) { return status; } /* we might be talking to NT4, so let's downgrade in that case and retry * with the returned neg_flags - gd */ if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) && !retried) { retried = true; TALLOC_FREE(cli->dc); goto again; } if (!NT_STATUS_IS_OK(result)) { return result; } /* * Check the returned value using the initial * server received challenge. */ if (!netlogon_creds_client_check(cli->dc, &srv_chal_recv)) { /* * Server replied with bad credential. Fail. */ DEBUG(0,("rpccli_netlogon_setup_creds: server %s " "replied with bad credential\n", cli->desthost )); return NT_STATUS_ACCESS_DENIED; } DEBUG(5,("rpccli_netlogon_setup_creds: server %s credential " "chain established.\n", cli->desthost )); cli->dc->negotiate_flags = neg_flags; *neg_flags_inout = neg_flags; return NT_STATUS_OK; }
static bool test_Map_tcpip(struct torture_context *tctx, struct dcerpc_binding_handle *h, struct ndr_syntax_id map_syntax) { struct epm_Map r; struct GUID uuid; struct policy_handle entry_handle; struct ndr_syntax_id syntax; struct dcerpc_binding map_binding; struct epm_twr_t map_tower; struct epm_twr_p_t towers[20]; struct epm_tower t; uint32_t num_towers; uint32_t port; uint32_t i; long int p; const char *tmp; const char *ip; char *ptr; NTSTATUS status; torture_comment(tctx, "Testing epm_Map\n"); ZERO_STRUCT(uuid); ZERO_STRUCT(entry_handle); r.in.object = &uuid; r.in.map_tower = &map_tower; r.in.entry_handle = &entry_handle; r.out.entry_handle = &entry_handle; r.in.max_towers = 10; r.out.towers = towers; r.out.num_towers = &num_towers; /* Create map tower */ map_binding.transport = NCACN_IP_TCP; map_binding.object = map_syntax; map_binding.host = "0.0.0.0"; map_binding.endpoint = "135"; status = dcerpc_binding_build_tower(tctx, &map_binding, &map_tower.tower); torture_assert_ntstatus_ok(tctx, status, "epm_Map_tcpip failed: can't create map_tower"); torture_comment(tctx, "epm_Map request for '%s':\n", ndr_interface_name(&map_syntax.uuid, map_syntax.if_version)); display_tower(tctx, &r.in.map_tower->tower); status = dcerpc_epm_Map_r(h, tctx, &r); torture_assert_ntstatus_ok(tctx, status, "epm_Map_simple failed"); torture_assert(tctx, r.out.result == EPMAPPER_STATUS_OK, "epm_Map_tcpip failed: result is not EPMAPPER_STATUS_OK"); /* Check the result */ t = r.out.towers[0].twr->tower; /* Check if we got the correct RPC interface identifier */ dcerpc_floor_get_lhs_data(&t.floors[0], &syntax); torture_assert(tctx, ndr_syntax_id_equal(&syntax, &map_syntax), "epm_Map_tcpip failed: Interface identifier mismatch"); torture_comment(tctx, "epm_Map_tcpip response for '%s':\n", ndr_interface_name(&syntax.uuid, syntax.if_version)); dcerpc_floor_get_lhs_data(&t.floors[1], &syntax); torture_assert(tctx, ndr_syntax_id_equal(&syntax, &ndr_transfer_syntax_ndr), "epm_Map_tcpip failed: floor 2 is not NDR encoded"); torture_assert(tctx, t.floors[2].lhs.protocol == EPM_PROTOCOL_NCACN, "epm_Map_tcpip failed: floor 3 is not NCACN_IP_TCP"); tmp = dcerpc_floor_get_rhs_data(tctx, &t.floors[3]); p = strtol(tmp, &ptr, 10); port = p & 0xffff; torture_assert(tctx, port > 1024 && port < 65535, "epm_Map_tcpip failed"); ip = dcerpc_floor_get_rhs_data(tctx, &t.floors[4]); torture_assert(tctx, is_ipaddress(ip), "epm_Map_tcpip failed"); for (i = 0; i < *r.out.num_towers; i++) { if (r.out.towers[i].twr) { display_tower(tctx, &t); } } return true; }
NTSTATUS cli_do_rpc_ndr(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const struct ndr_interface_table *table, uint32 opnum, void *r) { #ifdef AVM_SMALL return NT_STATUS_NO_MEMORY; #else prs_struct q_ps, r_ps; const struct ndr_interface_call *call; struct ndr_pull *pull; DATA_BLOB blob; struct ndr_push *push; NTSTATUS status; enum ndr_err_code ndr_err; SMB_ASSERT(ndr_syntax_id_equal(&table->syntax_id, &cli->abstract_syntax)); SMB_ASSERT(table->num_calls > opnum); call = &table->calls[opnum]; push = ndr_push_init_ctx(mem_ctx); if (!push) { return NT_STATUS_NO_MEMORY; } ndr_err = call->ndr_push(push, NDR_IN, r); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return ndr_map_error2ntstatus(ndr_err); } blob = ndr_push_blob(push); if (!prs_init_data_blob(&q_ps, &blob, mem_ctx)) { return NT_STATUS_NO_MEMORY; } talloc_free(push); prs_init_empty( &r_ps, mem_ctx, UNMARSHALL ); status = rpc_api_pipe_req(cli, opnum, &q_ps, &r_ps); prs_mem_free( &q_ps ); if (!NT_STATUS_IS_OK(status)) { prs_mem_free( &r_ps ); return status; } if (!prs_data_blob(&r_ps, &blob, mem_ctx)) { prs_mem_free( &r_ps ); return NT_STATUS_NO_MEMORY; } prs_mem_free( &r_ps ); pull = ndr_pull_init_blob(&blob, mem_ctx); if (pull == NULL) { return NT_STATUS_NO_MEMORY; } /* have the ndr parser alloc memory for us */ pull->flags |= LIBNDR_FLAG_REF_ALLOC; ndr_err = call->ndr_pull(pull, NDR_OUT, r); talloc_free(pull); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return ndr_map_error2ntstatus(ndr_err); } return NT_STATUS_OK; #endif }