_PUBLIC_ NTSTATUS dcerpc_binding_from_tower(TALLOC_CTX *mem_ctx, struct epm_tower *tower, struct dcerpc_binding **b_out) { NTSTATUS status; struct dcerpc_binding *binding; /* * A tower needs to have at least 4 floors to carry useful * information. Floor 3 is the transport identifier which defines * how many floors are required at least. */ if (tower->num_floors < 4) { return NT_STATUS_INVALID_PARAMETER; } binding = talloc_zero(mem_ctx, struct dcerpc_binding); NT_STATUS_HAVE_NO_MEMORY(binding); ZERO_STRUCT(binding->object); binding->options = NULL; binding->host = NULL; binding->target_hostname = NULL; binding->flags = 0; binding->assoc_group_id = 0; binding->transport = dcerpc_transport_by_tower(tower); if (binding->transport == (unsigned int)-1) { return NT_STATUS_NOT_SUPPORTED; } /* Set object uuid */ status = dcerpc_floor_get_lhs_data(&tower->floors[0], &binding->object); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Error pulling object uuid and version: %s", nt_errstr(status))); return status; } /* Ignore floor 1, it contains the NDR version info */ binding->options = NULL; /* Set endpoint */ if (tower->num_floors >= 4) { binding->endpoint = dcerpc_floor_get_rhs_data(binding, &tower->floors[3]); } else { binding->endpoint = NULL; } /* Set network address */ if (tower->num_floors >= 5) { binding->host = dcerpc_floor_get_rhs_data(binding, &tower->floors[4]); NT_STATUS_HAVE_NO_MEMORY(binding->host); binding->target_hostname = binding->host; } *b_out = binding; return NT_STATUS_OK; }
_PUBLIC_ NTSTATUS dcerpc_binding_from_tower(TALLOC_CTX *mem_ctx, struct epm_tower *tower, struct dcerpc_binding **b_out) { NTSTATUS status; struct dcerpc_binding *binding; binding = talloc(mem_ctx, struct dcerpc_binding); NT_STATUS_HAVE_NO_MEMORY(binding); ZERO_STRUCT(binding->object); binding->options = NULL; binding->host = NULL; binding->target_hostname = NULL; binding->flags = 0; binding->assoc_group_id = 0; binding->transport = dcerpc_transport_by_tower(tower); if (binding->transport == (unsigned int)-1) { return NT_STATUS_NOT_SUPPORTED; } if (tower->num_floors < 1) { return NT_STATUS_OK; } /* Set object uuid */ status = dcerpc_floor_get_lhs_data(&tower->floors[0], &binding->object); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Error pulling object uuid and version: %s", nt_errstr(status))); return status; } /* Ignore floor 1, it contains the NDR version info */ binding->options = NULL; /* Set endpoint */ if (tower->num_floors >= 4) { binding->endpoint = dcerpc_floor_get_rhs_data(mem_ctx, &tower->floors[3]); } else { binding->endpoint = NULL; } /* Set network address */ if (tower->num_floors >= 5) { binding->host = dcerpc_floor_get_rhs_data(mem_ctx, &tower->floors[4]); NT_STATUS_HAVE_NO_MEMORY(binding->host); binding->target_hostname = binding->host; } *b_out = binding; return NT_STATUS_OK; }
const char *epm_floor_string(TALLOC_CTX *mem_ctx, struct epm_floor *epm_floor) { struct dcerpc_syntax_id syntax; NTSTATUS status; switch(epm_floor->lhs.protocol) { case EPM_PROTOCOL_UUID: status = dcerpc_floor_get_lhs_data(epm_floor, &syntax); if (NT_STATUS_IS_OK(status)) { /* lhs is used: UUID */ char *uuidstr; if (GUID_equal(&syntax.uuid, &ndr_transfer_syntax.uuid)) { return "NDR"; } if (GUID_equal(&syntax.uuid, &ndr64_transfer_syntax.uuid)) { return "NDR64"; } uuidstr = GUID_string(mem_ctx, &syntax.uuid); return talloc_asprintf(mem_ctx, " uuid %s/0x%02x", uuidstr, syntax.if_version); } else { /* IPX */ return talloc_asprintf(mem_ctx, "IPX:%s", data_blob_hex_string(mem_ctx, &epm_floor->rhs.uuid.unknown)); } case EPM_PROTOCOL_NCACN: return "RPC-C"; case EPM_PROTOCOL_NCADG: return "RPC"; case EPM_PROTOCOL_NCALRPC: return "NCALRPC"; case EPM_PROTOCOL_DNET_NSP: return "DNET/NSP"; case EPM_PROTOCOL_IP: return talloc_asprintf(mem_ctx, "IP:%s", epm_floor->rhs.ip.ipaddr); case EPM_PROTOCOL_PIPE: return talloc_asprintf(mem_ctx, "PIPE:%s", epm_floor->rhs.pipe.path); case EPM_PROTOCOL_SMB: return talloc_asprintf(mem_ctx, "SMB:%s", epm_floor->rhs.smb.unc); case EPM_PROTOCOL_UNIX_DS: return talloc_asprintf(mem_ctx, "Unix:%s", epm_floor->rhs.unix_ds.path); case EPM_PROTOCOL_NETBIOS: return talloc_asprintf(mem_ctx, "NetBIOS:%s", epm_floor->rhs.netbios.name); case EPM_PROTOCOL_NETBEUI: return "NETBeui"; case EPM_PROTOCOL_SPX: return "SPX"; case EPM_PROTOCOL_NB_IPX: return "NB_IPX"; case EPM_PROTOCOL_HTTP: return talloc_asprintf(mem_ctx, "HTTP:%d", epm_floor->rhs.http.port); case EPM_PROTOCOL_TCP: return talloc_asprintf(mem_ctx, "TCP:%d", epm_floor->rhs.tcp.port); case EPM_PROTOCOL_UDP: return talloc_asprintf(mem_ctx, "UDP:%d", epm_floor->rhs.udp.port); default: return talloc_asprintf(mem_ctx, "UNK(%02x):", epm_floor->lhs.protocol); } }
static BOOL test_Map(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct epm_twr_t *twr) { NTSTATUS status; struct epm_Map r; struct GUID uuid; struct policy_handle handle; int i; struct dcerpc_syntax_id syntax; 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 = 100; dcerpc_floor_get_lhs_data(&twr->tower.floors[0], &syntax); printf("epm_Map results for '%s':\n", idl_pipe_name(&syntax.uuid, syntax.if_version)); 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; 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; 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(p, mem_ctx, &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(mem_ctx, &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(p, mem_ctx, &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(mem_ctx, &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(p, mem_ctx, &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(mem_ctx, &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(p, mem_ctx, &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(mem_ctx, &r.out.towers[i].twr->tower); } } } /* FIXME: Extend to do other protocols as well (ncacn_unix_stream, ncalrpc) */ 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; }