Copyright (C) Jelmer Vernooij 2004
Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
Copyright (C) Rafal Szczesniak 2006
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
{ "ncadg_ip_udp", NCACN_IP_UDP, 3,
{ EPM_PROTOCOL_NCADG, EPM_PROTOCOL_UDP, EPM_PROTOCOL_IP } },
{ "ncalrpc", NCALRPC, 2,
- { EPM_PROTOCOL_NCALRPC, EPM_PROTOCOL_PIPE } },
+ { EPM_PROTOCOL_NCALRPC, EPM_PROTOCOL_NAMED_PIPE } },
{ "ncacn_unix_stream", NCACN_UNIX_STREAM, 2,
{ EPM_PROTOCOL_NCACN, EPM_PROTOCOL_UNIX_DS } },
{ "ncadg_unix_dgram", NCADG_UNIX_DGRAM, 2,
{"padcheck", DCERPC_DEBUG_PAD_CHECK},
{"bigendian", DCERPC_PUSH_BIGENDIAN},
{"smb2", DCERPC_SMB2},
- {"hdrsign", DCERPC_HEADER_SIGNING}
+ {"hdrsign", DCERPC_HEADER_SIGNING},
+ {"ndr64", DCERPC_NDR64}
};
const char *epm_floor_string(TALLOC_CTX *mem_ctx, struct epm_floor *epm_floor)
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));
+ data_blob_hex_string_upper(mem_ctx, &epm_floor->rhs.uuid.unknown));
}
case EPM_PROTOCOL_NCACN:
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_NAMED_PIPE:
+ return talloc_asprintf(mem_ctx, "NAMED-PIPE:%s", epm_floor->rhs.named_pipe.path);
case EPM_PROTOCOL_SMB:
return talloc_asprintf(mem_ctx, "SMB:%s", epm_floor->rhs.smb.unc);
const char *t_name = NULL;
if (b->transport != NCA_UNKNOWN) {
- for (i=0;i<ARRAY_SIZE(transports);i++) {
- if (transports[i].transport == b->transport) {
- t_name = transports[i].name;
- }
- }
+ t_name = derpc_transport_string_by_transport(b->transport);
if (!t_name) {
return NULL;
}
if (p && PTR_DIFF(p, s) == 36) { /* 36 is the length of a UUID */
NTSTATUS status;
-
- status = GUID_from_string(s, &b->object.uuid);
+ DATA_BLOB blob = data_blob(s, 36);
+ status = GUID_from_data_blob(&blob, &b->object.uuid);
if (NT_STATUS_IS_ERR(status)) {
DEBUG(0, ("Failed parsing UUID\n"));
}
talloc_free(type);
-
+
s = p+1;
}
if (b->options[0] == NULL)
b->options = NULL;
-
+
*b_out = b;
return NT_STATUS_OK;
}
-_PUBLIC_ NTSTATUS dcerpc_floor_get_lhs_data(struct epm_floor *epm_floor, struct ndr_syntax_id *syntax)
+_PUBLIC_ NTSTATUS dcerpc_floor_get_lhs_data(const struct epm_floor *epm_floor,
+ struct ndr_syntax_id *syntax)
{
TALLOC_CTX *mem_ctx = talloc_init("floor_get_lhs_data");
- struct ndr_pull *ndr = ndr_pull_init_blob(&epm_floor->lhs.lhs_data, mem_ctx, NULL);
+ struct ndr_pull *ndr;
enum ndr_err_code ndr_err;
uint16_t if_version=0;
+ ndr = ndr_pull_init_blob(&epm_floor->lhs.lhs_data, mem_ctx, NULL);
+ if (ndr == NULL) {
+ talloc_free(mem_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
ndr->flags |= LIBNDR_FLAG_NOALIGN;
ndr_err = ndr_pull_GUID(ndr, NDR_SCALARS | NDR_BUFFERS, &syntax->uuid);
static DATA_BLOB dcerpc_floor_pack_lhs_data(TALLOC_CTX *mem_ctx, const struct ndr_syntax_id *syntax)
{
+ DATA_BLOB blob;
struct ndr_push *ndr = ndr_push_init_ctx(mem_ctx, NULL);
ndr->flags |= LIBNDR_FLAG_NOALIGN;
ndr_push_GUID(ndr, NDR_SCALARS | NDR_BUFFERS, &syntax->uuid);
ndr_push_uint16(ndr, NDR_SCALARS, syntax->if_version);
- return ndr_push_blob(ndr);
+ blob = ndr_push_blob(ndr);
+ talloc_steal(mem_ctx, blob.data);
+ talloc_free(ndr);
+ return blob;
+}
+
+static DATA_BLOB dcerpc_floor_pack_rhs_if_version_data(TALLOC_CTX *mem_ctx, const struct ndr_syntax_id *syntax)
+{
+ DATA_BLOB blob;
+ struct ndr_push *ndr = ndr_push_init_ctx(mem_ctx, NULL);
+
+ ndr->flags |= LIBNDR_FLAG_NOALIGN;
+
+ ndr_push_uint16(ndr, NDR_SCALARS, syntax->if_version >> 16);
+
+ blob = ndr_push_blob(ndr);
+ talloc_steal(mem_ctx, blob.data);
+ talloc_free(ndr);
+ return blob;
}
const char *dcerpc_floor_get_rhs_data(TALLOC_CTX *mem_ctx, struct epm_floor *epm_floor)
case EPM_PROTOCOL_TCP:
if (epm_floor->rhs.tcp.port == 0) return NULL;
return talloc_asprintf(mem_ctx, "%d", epm_floor->rhs.tcp.port);
-
+
case EPM_PROTOCOL_UDP:
if (epm_floor->rhs.udp.port == 0) return NULL;
return talloc_asprintf(mem_ctx, "%d", epm_floor->rhs.udp.port);
if (strlen(epm_floor->rhs.smb.unc) == 0) return NULL;
return talloc_strdup(mem_ctx, epm_floor->rhs.smb.unc);
- case EPM_PROTOCOL_PIPE:
- if (strlen(epm_floor->rhs.pipe.path) == 0) return NULL;
- return talloc_strdup(mem_ctx, epm_floor->rhs.pipe.path);
+ case EPM_PROTOCOL_NAMED_PIPE:
+ if (strlen(epm_floor->rhs.named_pipe.path) == 0) return NULL;
+ return talloc_strdup(mem_ctx, epm_floor->rhs.named_pipe.path);
case EPM_PROTOCOL_NETBIOS:
if (strlen(epm_floor->rhs.netbios.name) == 0) return NULL;
case EPM_PROTOCOL_NCALRPC:
return NULL;
-
+
case EPM_PROTOCOL_VINES_SPP:
return talloc_asprintf(mem_ctx, "%d", epm_floor->rhs.vines_spp.port);
-
+
case EPM_PROTOCOL_VINES_IPC:
return talloc_asprintf(mem_ctx, "%d", epm_floor->rhs.vines_ipc.port);
-
+
case EPM_PROTOCOL_STREETTALK:
return talloc_strdup(mem_ctx, epm_floor->rhs.streettalk.streettalk);
-
+
case EPM_PROTOCOL_UNIX_DS:
if (strlen(epm_floor->rhs.unix_ds.path) == 0) return NULL;
return talloc_strdup(mem_ctx, epm_floor->rhs.unix_ds.path);
-
+
case EPM_PROTOCOL_NULL:
return NULL;
case EPM_PROTOCOL_TCP:
epm_floor->rhs.tcp.port = atoi(data);
return NT_STATUS_OK;
-
+
case EPM_PROTOCOL_UDP:
epm_floor->rhs.udp.port = atoi(data);
return NT_STATUS_OK;
NT_STATUS_HAVE_NO_MEMORY(epm_floor->rhs.smb.unc);
return NT_STATUS_OK;
- case EPM_PROTOCOL_PIPE:
- epm_floor->rhs.pipe.path = talloc_strdup(mem_ctx, data);
- NT_STATUS_HAVE_NO_MEMORY(epm_floor->rhs.pipe.path);
+ case EPM_PROTOCOL_NAMED_PIPE:
+ epm_floor->rhs.named_pipe.path = talloc_strdup(mem_ctx, data);
+ NT_STATUS_HAVE_NO_MEMORY(epm_floor->rhs.named_pipe.path);
return NT_STATUS_OK;
case EPM_PROTOCOL_NETBIOS:
case EPM_PROTOCOL_NCALRPC:
return NT_STATUS_OK;
-
+
case EPM_PROTOCOL_VINES_SPP:
epm_floor->rhs.vines_spp.port = atoi(data);
return NT_STATUS_OK;
-
+
case EPM_PROTOCOL_VINES_IPC:
epm_floor->rhs.vines_ipc.port = atoi(data);
return NT_STATUS_OK;
-
+
case EPM_PROTOCOL_STREETTALK:
epm_floor->rhs.streettalk.streettalk = talloc_strdup(mem_ctx, data);
NT_STATUS_HAVE_NO_MEMORY(epm_floor->rhs.streettalk.streettalk);
return NT_STATUS_OK;
-
+
case EPM_PROTOCOL_UNIX_DS:
epm_floor->rhs.unix_ds.path = talloc_strdup(mem_ctx, data);
NT_STATUS_HAVE_NO_MEMORY(epm_floor->rhs.unix_ds.path);
return NT_STATUS_OK;
-
+
case EPM_PROTOCOL_NULL:
return NT_STATUS_OK;
return transports[i].transport;
}
}
-
+
/* Unknown transport */
return (unsigned int)-1;
}
-_PUBLIC_ enum dcerpc_transport_t dcerpc_transport_by_tower(struct epm_tower *tower)
+_PUBLIC_ enum dcerpc_transport_t dcerpc_transport_by_tower(const struct epm_tower *tower)
{
int i;
return transports[i].transport;
}
}
-
+
/* Unknown transport */
return (unsigned int)-1;
}
+_PUBLIC_ const char *derpc_transport_string_by_transport(enum dcerpc_transport_t t)
+{
+ int i;
+
+ for (i=0; i<ARRAY_SIZE(transports); i++) {
+ if (t == transports[i].transport) {
+ return transports[i].name;
+ }
+ }
+ return NULL;
+}
+
_PUBLIC_ NTSTATUS dcerpc_binding_from_tower(TALLOC_CTX *mem_ctx,
struct epm_tower *tower,
struct dcerpc_binding **b_out)
/* 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 */
return NT_STATUS_OK;
}
-_PUBLIC_ NTSTATUS dcerpc_binding_build_tower(TALLOC_CTX *mem_ctx, struct dcerpc_binding *binding, struct epm_tower *tower)
+_PUBLIC_ NTSTATUS dcerpc_binding_build_tower(TALLOC_CTX *mem_ctx,
+ const struct dcerpc_binding *binding,
+ struct epm_tower *tower)
{
const enum epm_protocol *protseq = NULL;
int num_protocols = -1, i;
NTSTATUS status;
-
+
/* Find transport */
for (i=0;i<ARRAY_SIZE(transports);i++) {
if (transports[i].transport == binding->transport) {
/* Floor 0 */
tower->floors[0].lhs.protocol = EPM_PROTOCOL_UUID;
- tower->floors[0].lhs.lhs_data = dcerpc_floor_pack_lhs_data(mem_ctx, &binding->object);
+ tower->floors[0].lhs.lhs_data = dcerpc_floor_pack_lhs_data(tower->floors, &binding->object);
+
+ tower->floors[0].rhs.uuid.unknown = dcerpc_floor_pack_rhs_if_version_data(tower->floors, &binding->object);
- tower->floors[0].rhs.uuid.unknown = data_blob_talloc_zero(mem_ctx, 2);
-
/* Floor 1 */
tower->floors[1].lhs.protocol = EPM_PROTOCOL_UUID;
- tower->floors[1].lhs.lhs_data = dcerpc_floor_pack_lhs_data(mem_ctx,
+ tower->floors[1].lhs.lhs_data = dcerpc_floor_pack_lhs_data(tower->floors,
&ndr_transfer_syntax);
-
- tower->floors[1].rhs.uuid.unknown = data_blob_talloc_zero(mem_ctx, 2);
-
+
+ tower->floors[1].rhs.uuid.unknown = data_blob_talloc_zero(tower->floors, 2);
+
/* Floor 2 to num_protocols */
for (i = 0; i < num_protocols; i++) {
tower->floors[2 + i].lhs.protocol = protseq[i];
- tower->floors[2 + i].lhs.lhs_data = data_blob_talloc(mem_ctx, NULL, 0);
+ tower->floors[2 + i].lhs.lhs_data = data_blob_talloc(tower->floors, NULL, 0);
ZERO_STRUCT(tower->floors[2 + i].rhs);
- dcerpc_floor_set_rhs_data(mem_ctx, &tower->floors[2 + i], "");
+ dcerpc_floor_set_rhs_data(tower->floors, &tower->floors[2 + i], "");
}
/* The 4th floor contains the endpoint */
if (num_protocols >= 2 && binding->endpoint) {
- status = dcerpc_floor_set_rhs_data(mem_ctx, &tower->floors[3], binding->endpoint);
+ status = dcerpc_floor_set_rhs_data(tower->floors, &tower->floors[3], binding->endpoint);
if (NT_STATUS_IS_ERR(status)) {
return status;
}
}
-
+
/* The 5th contains the network address */
if (num_protocols >= 3 && binding->host) {
if (is_ipaddress(binding->host)) {
- status = dcerpc_floor_set_rhs_data(mem_ctx, &tower->floors[4],
+ status = dcerpc_floor_set_rhs_data(tower->floors, &tower->floors[4],
binding->host);
} else {
/* note that we don't attempt to resolve the
are in the client code, and want to put in
a wildcard all-zeros IP for the server to
fill in */
- status = dcerpc_floor_set_rhs_data(mem_ctx, &tower->floors[4],
+ status = dcerpc_floor_set_rhs_data(tower->floors, &tower->floors[4],
"0.0.0.0");
}
if (NT_STATUS_IS_ERR(status)) {