*/
#include "includes.h"
+#include "../../lib/util/util_net.h"
#include "librpc/gen_ndr/ndr_epmapper.h"
#include "librpc/gen_ndr/ndr_misc.h"
#include "librpc/rpc/dcerpc.h"
#undef strcasecmp
+#undef strncasecmp
#define MAX_PROTSEQ 10
{"bigendian", DCERPC_PUSH_BIGENDIAN},
{"smb2", DCERPC_SMB2},
{"hdrsign", DCERPC_HEADER_SIGNING},
- {"ndr64", DCERPC_NDR64}
+ {"ndr64", DCERPC_NDR64},
+ {"localaddress", DCERPC_LOCALADDRESS}
};
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:
for (i=0;i<ARRAY_SIZE(ncacn_options);i++) {
if (b->flags & ncacn_options[i].flag) {
- s = talloc_asprintf_append_buffer(s, ",%s", ncacn_options[i].name);
+ if (ncacn_options[i].flag == DCERPC_LOCALADDRESS && b->localaddress) {
+ s = talloc_asprintf_append_buffer(s, ",%s=%s", ncacn_options[i].name,
+ b->localaddress);
+ } else {
+ s = talloc_asprintf_append_buffer(s, ",%s", ncacn_options[i].name);
+ }
if (!s) return NULL;
}
}
char *p;
int i, j, comma_count;
- b = talloc(mem_ctx, struct dcerpc_binding);
+ b = talloc_zero(mem_ctx, struct dcerpc_binding);
if (!b) {
return NT_STATUS_NO_MEMORY;
}
b->flags = 0;
b->assoc_group_id = 0;
b->endpoint = NULL;
+ b->localaddress = NULL;
if (!options) {
*b_out = b;
/* some options are pre-parsed for convenience */
for (i=0;b->options[i];i++) {
for (j=0;j<ARRAY_SIZE(ncacn_options);j++) {
- if (strcasecmp(ncacn_options[j].name, b->options[i]) == 0) {
+ size_t opt_len = strlen(ncacn_options[j].name);
+ if (strncasecmp(ncacn_options[j].name, b->options[i], opt_len) == 0) {
int k;
+ char c = b->options[i][opt_len];
+
+ if (ncacn_options[j].flag == DCERPC_LOCALADDRESS && c == '=') {
+ b->localaddress = talloc_strdup(b, &b->options[i][opt_len+1]);
+ } else if (c != 0) {
+ continue;
+ }
+
b->flags |= ncacn_options[j].flag;
for (k=i;b->options[k];k++) {
b->options[k] = b->options[k+1];
enum ndr_err_code ndr_err;
uint16_t if_version=0;
- ndr = ndr_pull_init_blob(&epm_floor->lhs.lhs_data, mem_ctx, NULL);
+ ndr = ndr_pull_init_blob(&epm_floor->lhs.lhs_data, mem_ctx);
if (ndr == NULL) {
talloc_free(mem_ctx);
return NT_STATUS_NO_MEMORY;
static DATA_BLOB dcerpc_floor_pack_lhs_data(TALLOC_CTX *mem_ctx, const struct ndr_syntax_id *syntax)
{
- struct ndr_push *ndr = ndr_push_init_ctx(mem_ctx, NULL);
+ DATA_BLOB blob;
+ struct ndr_push *ndr = ndr_push_init_ctx(mem_ctx);
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);
+
+ 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)
NTSTATUS status;
struct dcerpc_binding *binding;
- binding = talloc(mem_ctx, struct dcerpc_binding);
+ binding = talloc_zero(mem_ctx, struct dcerpc_binding);
NT_STATUS_HAVE_NO_MEMORY(binding);
ZERO_STRUCT(binding->object);
/* Set endpoint */
if (tower->num_floors >= 4) {
- binding->endpoint = dcerpc_floor_get_rhs_data(mem_ctx, &tower->floors[3]);
+ 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(mem_ctx, &tower->floors[4]);
+ binding->host = dcerpc_floor_get_rhs_data(binding, &tower->floors[4]);
NT_STATUS_HAVE_NO_MEMORY(binding->host);
binding->target_hostname = binding->host;
}
/* 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 = data_blob_talloc_zero(mem_ctx, 2);
+ tower->floors[0].rhs.uuid.unknown = dcerpc_floor_pack_rhs_if_version_data(tower->floors, &binding->object);
/* 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],
+ if (is_ipaddress(binding->host) ||
+ (binding->host[0] == '\\' && binding->host[1] == '\\')) {
+ 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)) {