void *_policy_handle_create(struct pipes_struct *p, struct policy_handle *hnd, uint32_t access_granted, size_t data_size, const char *type, NTSTATUS *pstatus) { struct dcesrv_handle *rpc_hnd; void *data; if (p->pipe_handles->count > MAX_OPEN_POLS) { DEBUG(0, ("ERROR: Too many handles (%d) for RPC connection %s\n", (int) p->pipe_handles->count, ndr_interface_name(&p->contexts->syntax.uuid, p->contexts->syntax.if_version))); *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES; return NULL; } data = talloc_size(talloc_tos(), data_size); if (data == NULL) { *pstatus = NT_STATUS_NO_MEMORY; return NULL; } talloc_set_name_const(data, type); rpc_hnd = create_rpc_handle_internal(p, hnd, data); if (rpc_hnd == NULL) { TALLOC_FREE(data); *pstatus = NT_STATUS_NO_MEMORY; return NULL; } rpc_hnd->access_granted = access_granted; *pstatus = NT_STATUS_OK; return data; }
/* ask the server what interface IDs are available on this endpoint */ bool test_inq_if_ids(struct torture_context *tctx, struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, bool (*per_id_test)(struct torture_context *, const struct ndr_interface_table *iface, TALLOC_CTX *mem_ctx, struct ndr_syntax_id *id), const void *priv) { NTSTATUS status; struct mgmt_inq_if_ids r; struct rpc_if_id_vector_t *vector; int i; vector = talloc(mem_ctx, struct rpc_if_id_vector_t); r.out.if_id_vector = &vector; status = dcerpc_mgmt_inq_if_ids(p, mem_ctx, &r); if (!NT_STATUS_IS_OK(status)) { printf("inq_if_ids failed - %s\n", nt_errstr(status)); return false; } if (!W_ERROR_IS_OK(r.out.result)) { printf("inq_if_ids gave error code %s\n", win_errstr(r.out.result)); return false; } if (!vector) { printf("inq_if_ids gave NULL if_id_vector\n"); return false; } for (i=0;i<vector->count;i++) { struct ndr_syntax_id *id = vector->if_id[i].id; if (!id) continue; printf("\tuuid %s version 0x%08x '%s'\n", GUID_string(mem_ctx, &id->uuid), id->if_version, ndr_interface_name(&id->uuid, id->if_version)); if (per_id_test) { per_id_test(tctx, priv, mem_ctx, id); } } 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 bool api_pipe_request(struct pipes_struct *p, struct ncacn_packet *pkt) { bool ret = False; struct pipe_rpc_fns *pipe_fns; if (!p->pipe_bound) { DEBUG(1, ("Pipe not bound!\n")); data_blob_free(&p->out_data.rdata); return false; } if (!become_authenticated_pipe_user(p->session_info)) { DEBUG(1, ("Failed to become pipe user!\n")); data_blob_free(&p->out_data.rdata); return false; } /* get the set of RPC functions for this context */ pipe_fns = find_pipe_fns_by_context(p->contexts, pkt->u.request.context_id); if ( pipe_fns ) { TALLOC_CTX *frame = talloc_stackframe(); DEBUG(5, ("Requested %s rpc service\n", ndr_interface_name(&pipe_fns->syntax.uuid, pipe_fns->syntax.if_version))); ret = api_rpcTNP(p, pkt, pipe_fns->cmds, pipe_fns->n_cmds, &pipe_fns->syntax); TALLOC_FREE(frame); } else { DEBUG(0, ("No rpc function table associated with context " "[%d]\n", pkt->u.request.context_id)); } unbecome_authenticated_pipe_user(); return ret; }
void close_policy_by_pipe(struct pipes_struct *p) { if (p->pipe_handles == NULL) { return; } p->pipe_handles->pipe_ref_count--; if (p->pipe_handles->pipe_ref_count == 0) { /* * Last pipe open on this list - free the list. */ TALLOC_FREE(p->pipe_handles); DEBUG(10,("Deleted handle list for RPC connection %s\n", ndr_interface_name(&p->contexts->syntax.uuid, p->contexts->syntax.if_version))); } }
static bool api_pipe_bind_req(struct pipes_struct *p, struct ncacn_packet *pkt) { struct dcerpc_auth auth_info = {0}; uint16_t assoc_gid; unsigned int auth_type = DCERPC_AUTH_TYPE_NONE; NTSTATUS status; struct ndr_syntax_id id; uint8_t pfc_flags = 0; union dcerpc_payload u; struct dcerpc_ack_ctx bind_ack_ctx; DATA_BLOB auth_resp = data_blob_null; DATA_BLOB auth_blob = data_blob_null; const struct ndr_interface_table *table; /* No rebinds on a bound pipe - use alter context. */ if (p->pipe_bound) { DEBUG(2,("Rejecting bind request on bound rpc connection\n")); return setup_bind_nak(p, pkt); } if (pkt->u.bind.num_contexts == 0) { DEBUG(0, ("api_pipe_bind_req: no rpc contexts around\n")); goto err_exit; } /* * Try and find the correct pipe name to ensure * that this is a pipe name we support. */ id = pkt->u.bind.ctx_list[0].abstract_syntax; table = ndr_table_by_uuid(&id.uuid); if (table == NULL) { DEBUG(0,("unknown interface\n")); return false; } if (rpc_srv_pipe_exists_by_id(&id)) { DEBUG(3, ("api_pipe_bind_req: %s -> %s rpc service\n", rpc_srv_get_pipe_cli_name(&id), rpc_srv_get_pipe_srv_name(&id))); } else { status = smb_probe_module( "rpc", dcerpc_default_transport_endpoint(pkt, NCACN_NP, table)); if (NT_STATUS_IS_ERR(status)) { DEBUG(3,("api_pipe_bind_req: Unknown rpc service name " "%s in bind request.\n", ndr_interface_name(&id.uuid, id.if_version))); return setup_bind_nak(p, pkt); } if (rpc_srv_get_pipe_interface_by_cli_name( dcerpc_default_transport_endpoint(pkt, NCACN_NP, table), &id)) { DEBUG(3, ("api_pipe_bind_req: %s -> %s rpc service\n", rpc_srv_get_pipe_cli_name(&id), rpc_srv_get_pipe_srv_name(&id))); } else { DEBUG(0, ("module %s doesn't provide functions for " "pipe %s!\n", ndr_interface_name(&id.uuid, id.if_version), ndr_interface_name(&id.uuid, id.if_version))); return setup_bind_nak(p, pkt); } } DEBUG(5,("api_pipe_bind_req: make response. %d\n", __LINE__)); if (pkt->u.bind.assoc_group_id != 0) { assoc_gid = pkt->u.bind.assoc_group_id; } else { assoc_gid = 0x53f0; } /* * Create the bind response struct. */ /* If the requested abstract synt uuid doesn't match our client pipe, reject the bind_ack & set the transfer interface synt to all 0's, ver 0 (observed when NT5 attempts to bind to abstract interfaces unknown to NT4) Needed when adding entries to a DACL from NT5 - SK */ if (check_bind_req(p, &pkt->u.bind.ctx_list[0].abstract_syntax, &pkt->u.bind.ctx_list[0].transfer_syntaxes[0], pkt->u.bind.ctx_list[0].context_id)) { bind_ack_ctx.result = 0; bind_ack_ctx.reason.value = 0; bind_ack_ctx.syntax = pkt->u.bind.ctx_list[0].transfer_syntaxes[0]; } else { p->pipe_bound = False; /* Rejection reason: abstract syntax not supported */ bind_ack_ctx.result = DCERPC_BIND_PROVIDER_REJECT; bind_ack_ctx.reason.value = DCERPC_BIND_REASON_ASYNTAX; bind_ack_ctx.syntax = ndr_syntax_id_null; } /* * Check if this is an authenticated bind request. */ if (pkt->auth_length) { /* Quick length check. Won't catch a bad auth footer, * prevents overrun. */ if (pkt->frag_length < RPC_HEADER_LEN + DCERPC_AUTH_TRAILER_LENGTH + pkt->auth_length) { DEBUG(0,("api_pipe_bind_req: auth_len (%u) " "too long for fragment %u.\n", (unsigned int)pkt->auth_length, (unsigned int)pkt->frag_length)); goto err_exit; } /* * Decode the authentication verifier. */ status = dcerpc_pull_dcerpc_auth(pkt, &pkt->u.bind.auth_info, &auth_info, p->endian); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Unable to unmarshall dcerpc_auth.\n")); goto err_exit; } auth_type = auth_info.auth_type; /* Work out if we have to sign or seal etc. */ switch (auth_info.auth_level) { case DCERPC_AUTH_LEVEL_INTEGRITY: p->auth.auth_level = DCERPC_AUTH_LEVEL_INTEGRITY; break; case DCERPC_AUTH_LEVEL_PRIVACY: p->auth.auth_level = DCERPC_AUTH_LEVEL_PRIVACY; break; case DCERPC_AUTH_LEVEL_CONNECT: p->auth.auth_level = DCERPC_AUTH_LEVEL_CONNECT; break; default: DEBUG(0, ("Unexpected auth level (%u).\n", (unsigned int)auth_info.auth_level )); goto err_exit; } switch (auth_type) { case DCERPC_AUTH_TYPE_NONE: break; default: if (!pipe_auth_generic_bind(p, pkt, &auth_info, &auth_resp)) { goto err_exit; } break; } } if (auth_type == DCERPC_AUTH_TYPE_NONE) { /* Unauthenticated bind request. */ /* We're finished - no more packets. */ p->auth.auth_type = DCERPC_AUTH_TYPE_NONE; /* We must set the pipe auth_level here also. */ p->auth.auth_level = DCERPC_AUTH_LEVEL_NONE; p->pipe_bound = True; /* The session key was initialized from the SMB * session in make_internal_rpc_pipe_p */ } ZERO_STRUCT(u.bind_ack); u.bind_ack.max_xmit_frag = RPC_MAX_PDU_FRAG_LEN; u.bind_ack.max_recv_frag = RPC_MAX_PDU_FRAG_LEN; u.bind_ack.assoc_group_id = assoc_gid; /* name has to be \PIPE\xxxxx */ u.bind_ack.secondary_address = talloc_asprintf(pkt, "\\PIPE\\%s", rpc_srv_get_pipe_srv_name(&id)); if (!u.bind_ack.secondary_address) { DEBUG(0, ("Out of memory!\n")); goto err_exit; } u.bind_ack.secondary_address_size = strlen(u.bind_ack.secondary_address) + 1; u.bind_ack.num_results = 1; u.bind_ack.ctx_list = &bind_ack_ctx; /* NOTE: We leave the auth_info empty so we can calculate the padding * later and then append the auth_info --simo */ /* * Marshall directly into the outgoing PDU space. We * must do this as we need to set to the bind response * header and are never sending more than one PDU here. */ pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST; if (p->auth.hdr_signing) { pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN; } status = dcerpc_push_ncacn_packet(p->mem_ctx, DCERPC_PKT_BIND_ACK, pfc_flags, auth_resp.length, pkt->call_id, &u, &p->out_data.frag); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Failed to marshall bind_ack packet. (%s)\n", nt_errstr(status))); } if (auth_resp.length) { status = dcerpc_push_dcerpc_auth(pkt, auth_type, auth_info.auth_level, 0, 1, /* auth_context_id */ &auth_resp, &auth_blob); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Marshalling of dcerpc_auth failed.\n")); goto err_exit; } } /* Now that we have the auth len store it into the right place in * the dcerpc header */ dcerpc_set_frag_length(&p->out_data.frag, p->out_data.frag.length + auth_blob.length); if (auth_blob.length) { if (!data_blob_append(p->mem_ctx, &p->out_data.frag, auth_blob.data, auth_blob.length)) { DEBUG(0, ("Append of auth info failed.\n")); goto err_exit; } } /* * Setup the lengths for the initial reply. */ p->out_data.data_sent_length = 0; p->out_data.current_pdu_sent = 0; TALLOC_FREE(auth_blob.data); return True; err_exit: data_blob_free(&p->out_data.frag); TALLOC_FREE(auth_blob.data); return setup_bind_nak(p, pkt); }
static bool api_rpcTNP(struct pipes_struct *p, struct ncacn_packet *pkt, const struct api_struct *api_rpc_cmds, int n_cmds, const struct ndr_syntax_id *syntax) { int fn_num; uint32_t offset1; const struct ndr_interface_table *table; /* interpret the command */ DEBUG(4,("api_rpcTNP: %s op 0x%x - ", ndr_interface_name(&syntax->uuid, syntax->if_version), pkt->u.request.opnum)); table = ndr_table_by_uuid(&syntax->uuid); if (table == NULL) { DEBUG(0,("unknown interface\n")); return false; } if (DEBUGLEVEL >= 50) { fstring name; slprintf(name, sizeof(name)-1, "in_%s", dcerpc_default_transport_endpoint(pkt, NCACN_NP, table)); dump_pdu_region(name, pkt->u.request.opnum, &p->in_data.data, 0, p->in_data.data.length); } for (fn_num = 0; fn_num < n_cmds; fn_num++) { if (api_rpc_cmds[fn_num].opnum == pkt->u.request.opnum && api_rpc_cmds[fn_num].fn != NULL) { DEBUG(3, ("api_rpcTNP: rpc command: %s\n", api_rpc_cmds[fn_num].name)); break; } } if (fn_num == n_cmds) { /* * For an unknown RPC just return a fault PDU but * return True to allow RPC's on the pipe to continue * and not put the pipe into fault state. JRA. */ DEBUG(4, ("unknown\n")); setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR)); return True; } offset1 = p->out_data.rdata.length; DEBUG(6, ("api_rpc_cmds[%d].fn == %p\n", fn_num, api_rpc_cmds[fn_num].fn)); /* do the actual command */ if(!api_rpc_cmds[fn_num].fn(p)) { DEBUG(0,("api_rpcTNP: %s: %s failed.\n", ndr_interface_name(&syntax->uuid, syntax->if_version), api_rpc_cmds[fn_num].name)); data_blob_free(&p->out_data.rdata); return False; } if (p->fault_state) { DEBUG(4,("api_rpcTNP: fault(%d) return.\n", p->fault_state)); setup_fault_pdu(p, NT_STATUS(p->fault_state)); p->fault_state = 0; return true; } if (DEBUGLEVEL >= 50) { fstring name; slprintf(name, sizeof(name)-1, "out_%s", dcerpc_default_transport_endpoint(pkt, NCACN_NP, table)); dump_pdu_region(name, pkt->u.request.opnum, &p->out_data.rdata, offset1, p->out_data.rdata.length); } DEBUG(5,("api_rpcTNP: called %s successfully\n", ndr_interface_name(&syntax->uuid, syntax->if_version))); /* Check for buffer underflow in rpc parsing */ if ((DEBUGLEVEL >= 10) && (pkt->frag_length < p->in_data.data.length)) { DEBUG(10, ("api_rpcTNP: rpc input buffer underflow (parse error?)\n")); dump_data(10, p->in_data.data.data + pkt->frag_length, p->in_data.data.length - pkt->frag_length); } return True; }
static bool srv_pipe_check_verification_trailer(struct pipes_struct *p, struct ncacn_packet *pkt, struct pipe_rpc_fns *pipe_fns) { TALLOC_CTX *frame = talloc_stackframe(); struct dcerpc_sec_verification_trailer *vt = NULL; const uint32_t bitmask1 = p->auth.client_hdr_signing ? DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING : 0; const struct dcerpc_sec_vt_pcontext pcontext = { .abstract_syntax = pipe_fns->syntax, .transfer_syntax = ndr_transfer_syntax_ndr, }; const struct dcerpc_sec_vt_header2 header2 = dcerpc_sec_vt_header2_from_ncacn_packet(pkt); struct ndr_pull *ndr; enum ndr_err_code ndr_err; bool ret = false; ndr = ndr_pull_init_blob(&p->in_data.data, frame); if (ndr == NULL) { goto done; } ndr_err = ndr_pop_dcerpc_sec_verification_trailer(ndr, frame, &vt); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { goto done; } ret = dcerpc_sec_verification_trailer_check(vt, &bitmask1, &pcontext, &header2); done: TALLOC_FREE(frame); return ret; } /**************************************************************************** Find the correct RPC function to call for this request. If the pipe is authenticated then become the correct UNIX user before doing the call. ****************************************************************************/ static bool api_pipe_request(struct pipes_struct *p, struct ncacn_packet *pkt) { TALLOC_CTX *frame = talloc_stackframe(); bool ret = False; struct pipe_rpc_fns *pipe_fns; if (!p->pipe_bound) { DEBUG(1, ("Pipe not bound!\n")); data_blob_free(&p->out_data.rdata); TALLOC_FREE(frame); return false; } /* get the set of RPC functions for this context */ pipe_fns = find_pipe_fns_by_context(p->contexts, pkt->u.request.context_id); if (pipe_fns == NULL) { DEBUG(0, ("No rpc function table associated with context " "[%d]\n", pkt->u.request.context_id)); data_blob_free(&p->out_data.rdata); TALLOC_FREE(frame); return false; } if (!srv_pipe_check_verification_trailer(p, pkt, pipe_fns)) { DEBUG(1, ("srv_pipe_check_verification_trailer: failed\n")); setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_ACCESS_DENIED)); data_blob_free(&p->out_data.rdata); TALLOC_FREE(frame); return true; } if (!become_authenticated_pipe_user(p->session_info)) { DEBUG(1, ("Failed to become pipe user!\n")); data_blob_free(&p->out_data.rdata); TALLOC_FREE(frame); return false; } DEBUG(5, ("Requested %s rpc service\n", ndr_interface_name(&pipe_fns->syntax.uuid, pipe_fns->syntax.if_version))); ret = api_rpcTNP(p, pkt, pipe_fns->cmds, pipe_fns->n_cmds, &pipe_fns->syntax); unbecome_authenticated_pipe_user(); TALLOC_FREE(frame); return ret; }
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", ndr_interface_name(&syntax->uuid, syntax->if_version))); } /* * 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, ndr_interface_name(&syntax->uuid, syntax->if_version))); return True; }
static bool test_Map_display(struct dcerpc_binding_handle *b, struct torture_context *tctx, struct epm_twr_t *twr) { NTSTATUS status; struct epm_Map r; struct GUID uuid; struct policy_handle handle; struct ndr_syntax_id syntax; uint32_t num_towers; uint32_t i; ZERO_STRUCT(uuid); ZERO_STRUCT(handle); r.in.object = &uuid; r.in.map_tower = twr; r.in.entry_handle = &handle; r.out.entry_handle = &handle; r.in.max_towers = 10; r.out.num_towers = &num_towers; dcerpc_floor_get_lhs_data(&twr->tower.floors[0], &syntax); torture_comment(tctx, "epm_Map results for '%s':\n", ndr_interface_name(&syntax.uuid, syntax.if_version)); /* RPC protocol identifier */ twr->tower.floors[2].lhs.protocol = EPM_PROTOCOL_NCACN; twr->tower.floors[2].lhs.lhs_data = data_blob(NULL, 0); twr->tower.floors[2].rhs.ncacn.minor_version = 0; /* Port address */ twr->tower.floors[3].lhs.protocol = EPM_PROTOCOL_TCP; twr->tower.floors[3].lhs.lhs_data = data_blob(NULL, 0); twr->tower.floors[3].rhs.tcp.port = 0; /* Transport */ twr->tower.floors[4].lhs.protocol = EPM_PROTOCOL_IP; twr->tower.floors[4].lhs.lhs_data = data_blob(NULL, 0); twr->tower.floors[4].rhs.ip.ipaddr = "0.0.0.0"; status = dcerpc_epm_Map_r(b, tctx, &r); if (NT_STATUS_IS_OK(status) && r.out.result == 0) { for (i=0;i<*r.out.num_towers;i++) { if (r.out.towers[i].twr) { display_tower(tctx, &r.out.towers[i].twr->tower); } } } twr->tower.floors[3].lhs.protocol = EPM_PROTOCOL_HTTP; twr->tower.floors[3].lhs.lhs_data = data_blob(NULL, 0); twr->tower.floors[3].rhs.http.port = 0; status = dcerpc_epm_Map_r(b, tctx, &r); if (NT_STATUS_IS_OK(status) && r.out.result == 0) { for (i=0;i<*r.out.num_towers;i++) { if (r.out.towers[i].twr) { display_tower(tctx, &r.out.towers[i].twr->tower); } } } twr->tower.floors[3].lhs.protocol = EPM_PROTOCOL_UDP; twr->tower.floors[3].lhs.lhs_data = data_blob(NULL, 0); twr->tower.floors[3].rhs.http.port = 0; status = dcerpc_epm_Map_r(b, tctx, &r); if (NT_STATUS_IS_OK(status) && r.out.result == 0) { for (i=0;i<*r.out.num_towers;i++) { if (r.out.towers[i].twr) { display_tower(tctx, &r.out.towers[i].twr->tower); } } } twr->tower.floors[3].lhs.protocol = EPM_PROTOCOL_SMB; twr->tower.floors[3].lhs.lhs_data = data_blob(NULL, 0); twr->tower.floors[3].rhs.smb.unc = ""; twr->tower.floors[4].lhs.protocol = EPM_PROTOCOL_NETBIOS; twr->tower.floors[4].lhs.lhs_data = data_blob(NULL, 0); twr->tower.floors[4].rhs.netbios.name = ""; status = dcerpc_epm_Map_r(b, tctx, &r); if (NT_STATUS_IS_OK(status) && r.out.result == 0) { for (i = 0; i < *r.out.num_towers; i++) { if (r.out.towers[i].twr) { display_tower(tctx, &r.out.towers[i].twr->tower); } } } /* FIXME: Extend to do other protocols as well (ncacn_unix_stream, ncalrpc) */ return true; }
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; }