diff options
-rw-r--r-- | source4/librpc/rpc/dcerpc_util.c | 136 | ||||
-rw-r--r-- | source4/torture/local/binding_string.c | 76 |
2 files changed, 193 insertions, 19 deletions
diff --git a/source4/librpc/rpc/dcerpc_util.c b/source4/librpc/rpc/dcerpc_util.c index 3b4f7a7efb..f1b120894e 100644 --- a/source4/librpc/rpc/dcerpc_util.c +++ b/source4/librpc/rpc/dcerpc_util.c @@ -300,9 +300,13 @@ const char *dcerpc_binding_string(TALLOC_CTX *mem_ctx, const struct dcerpc_bindi s = talloc_asprintf(mem_ctx, "%s@", GUID_string(mem_ctx, b->object)); } - s = talloc_asprintf_append(s, "%s:%s", t_name, b->host); + s = talloc_asprintf_append(s, "%s:", t_name); if (!s) return NULL; + if (b->host) { + s = talloc_asprintf_append(s, "%s", b->host); + } + if ((!b->options || !b->options[0]) && !b->flags) { return s; } @@ -438,6 +442,69 @@ NTSTATUS dcerpc_parse_binding(TALLOC_CTX *mem_ctx, const char *s, struct dcerpc_ return NT_STATUS_OK; } +static const char *floor_get_rhs_data(TALLOC_CTX *mem_ctx, struct epm_floor *floor) +{ + switch (floor->lhs.protocol) { + case EPM_PROTOCOL_TCP: + if (floor->rhs.tcp.port == 0) return NULL; + return talloc_asprintf(mem_ctx, "%d", floor->rhs.tcp.port); + + case EPM_PROTOCOL_UDP: + if (floor->rhs.udp.port == 0) return NULL; + return talloc_asprintf(mem_ctx, "%d", floor->rhs.udp.port); + + case EPM_PROTOCOL_HTTP: + if (floor->rhs.http.port == 0) return NULL; + return talloc_asprintf(mem_ctx, "%d", floor->rhs.http.port); + + case EPM_PROTOCOL_IP: + if (floor->rhs.ip.address == 0) { + return NULL; + } + + { + struct in_addr in; + in.s_addr = htonl(floor->rhs.ip.address); + return talloc_strdup(mem_ctx, inet_ntoa(in)); + } + + case EPM_PROTOCOL_NCACN: + return NULL; + + case EPM_PROTOCOL_NCADG: + return NULL; + + case EPM_PROTOCOL_SMB: + return talloc_strdup(mem_ctx, floor->rhs.smb.unc); + + case EPM_PROTOCOL_PIPE: + return talloc_strdup(mem_ctx, floor->rhs.pipe.path); + + case EPM_PROTOCOL_NETBIOS: + return talloc_strdup(mem_ctx, floor->rhs.netbios.name); + + case EPM_PROTOCOL_NCALRPC: + return NULL; + + case EPM_PROTOCOL_VINES_SPP: + return talloc_asprintf(mem_ctx, "%d", floor->rhs.vines_spp.port); + + case EPM_PROTOCOL_VINES_IPC: + return talloc_asprintf(mem_ctx, "%d", floor->rhs.vines_ipc.port); + + case EPM_PROTOCOL_STREETTALK: + return talloc_strdup(mem_ctx, floor->rhs.streettalk.streettalk); + + case EPM_PROTOCOL_UNIX_DS: + return talloc_strdup(mem_ctx, floor->rhs.unix_ds.path); + + case EPM_PROTOCOL_NULL: + return NULL; + } + + return NULL; +} + static NTSTATUS floor_set_rhs_data(TALLOC_CTX *mem_ctx, struct epm_floor *floor, const char *data) { switch (floor->lhs.protocol) { @@ -464,12 +531,13 @@ static NTSTATUS floor_set_rhs_data(TALLOC_CTX *mem_ctx, struct epm_floor *floor, memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_INET; + hints.ai_protocol = PF_INET; if (getaddrinfo(data, NULL, &hints, &res) < 0) { return NT_STATUS_BAD_NETWORK_NAME; } - floor->rhs.ip.address = ntohl(((struct in_addr *)res->ai_addr)->s_addr); + floor->rhs.ip.address = ntohl(((struct sockaddr_in *)res->ai_addr)->sin_addr.s_addr); freeaddrinfo(res); } @@ -536,6 +604,67 @@ static NTSTATUS floor_set_rhs_data(TALLOC_CTX *mem_ctx, struct epm_floor *floor, return NT_STATUS_NOT_SUPPORTED; } +NTSTATUS dcerpc_binding_from_tower(TALLOC_CTX *mem_ctx, struct epm_tower *tower, struct dcerpc_binding *binding) +{ + int i; + + binding->transport = -1; + binding->object = NULL; + binding->options = NULL; + binding->host = NULL; + binding->flags = 0; + + /* Find a transport that matches this tower */ + for (i=0;i<ARRAY_SIZE(transports);i++) { + int j; + if (transports[i].num_protocols != tower->num_floors - 2) { + continue; + } + + for (j = 0; j < transports[i].num_protocols; j++) { + if (transports[i].protseq[j] != tower->floors[j+2].lhs.protocol) { + break; + } + } + + if (j == transports[i].num_protocols) { + binding->transport = transports[i].transport; + break; + } + } + + if (binding->transport == -1) { + return NT_STATUS_NOT_SUPPORTED; + } + + if (tower->num_floors < 1) { + return NT_STATUS_OK; + } + + /* Set object uuid */ + if (!uuid_all_zero(&tower->floors[0].lhs.info.uuid.uuid)) { + binding->object = talloc_p(mem_ctx, struct GUID); + *binding->object = tower->floors[0].lhs.info.uuid.uuid; + } + + /* Ignore floor 1, it contains the NDR version info */ + + binding->options = talloc_array_p(mem_ctx, const char *, 2); + + /* Set endpoint */ + if (tower->num_floors >= 3) { + binding->options[0] = floor_get_rhs_data(mem_ctx, &tower->floors[tower->num_floors-1]); + } else { + binding->options[0] = NULL; + } + binding->options[1] = NULL; + + /* Set network address */ + if (tower->num_floors >= 4) { + binding->host = floor_get_rhs_data(mem_ctx, &tower->floors[tower->num_floors-2]); + } + return NT_STATUS_OK; +} NTSTATUS dcerpc_binding_build_tower(TALLOC_CTX *mem_ctx, struct dcerpc_binding *binding, struct epm_tower **tower) { @@ -570,6 +699,8 @@ NTSTATUS dcerpc_binding_build_tower(TALLOC_CTX *mem_ctx, struct dcerpc_binding * (*tower)->floors[0].lhs.protocol = EPM_PROTOCOL_UUID; if (binding->object) { (*tower)->floors[0].lhs.info.uuid.uuid = *binding->object; + } else { + ZERO_STRUCT((*tower)->floors[0].lhs.info.uuid.uuid); } (*tower)->floors[0].lhs.info.uuid.version = 0; @@ -584,6 +715,7 @@ NTSTATUS dcerpc_binding_build_tower(TALLOC_CTX *mem_ctx, struct dcerpc_binding * /* Floor 2 to num_protocols */ for (i = 0; i < num_protocols; i++) { (*tower)->floors[2 + i].lhs.protocol = protseq[i]; + ZERO_STRUCT((*tower)->floors[2 + i].rhs); } /* The top floor contains the endpoint */ diff --git a/source4/torture/local/binding_string.c b/source4/torture/local/binding_string.c index 26fe67dd5c..7ec9a30d24 100644 --- a/source4/torture/local/binding_string.c +++ b/source4/torture/local/binding_string.c @@ -22,11 +22,10 @@ #include "includes.h" -static BOOL test_BindingString(const char *binding) +static BOOL test_BindingString(TALLOC_CTX *mem_ctx, const char *binding) { - TALLOC_CTX *mem_ctx = talloc_init("test_BindingString"); - struct dcerpc_binding b; - const char *s; + struct dcerpc_binding b, b2; + const char *s, *s2; struct epm_tower *tower; NTSTATUS status; @@ -55,27 +54,70 @@ static BOOL test_BindingString(const char *binding) return False; } - /* FIXME: Convert back to binding and then back to string and compare */ + /* Convert back to binding and then back to string and compare */ + + status = dcerpc_binding_from_tower(mem_ctx, tower, &b2); + if (NT_STATUS_IS_ERR(status)) { + DEBUG(0, ("Error generating binding from tower for original binding '%s': %s\n", binding, nt_errstr(status))); + return False; + } + + /* Compare to a stripped down version of the binding string because + * the protocol tower doesn't contain the extra option data */ + if (b.options && b.options[0]) { + b.options[1] = NULL; + } + + b.flags = 0; + + s = dcerpc_binding_string(mem_ctx, &b); + if (!s) { + DEBUG(0, ("Error converting binding back to string for (stripped down) '%s'\n", binding)); + return False; + } + + + s2 = dcerpc_binding_string(mem_ctx, &b2); + if (!s) { + DEBUG(0, ("Error converting binding back to string for '%s'\n", binding)); + return False; + } + + if (strcasecmp(s, s2) != 0) { + DEBUG(0, ("Mismatch while comparing original and from protocol tower generated binding strings: '%s' <> '%s'\n", s, s2)); + return False; + } return True; } +static const char *test_strings[] = { + "ncacn_np:", + "ncalrpc:", + "ncalrpc:[Security=Sane]", + "ncacn_np:[rpcecho]", + "ncacn_np:127.0.0.1[rpcecho]", + "ncacn_ip_tcp:127.0.0.1", + "ncacn_np:localhost[rpcecho]", + "ncacn_np:[/pipe/rpcecho]", + "ncacn_np:localhost[/pipe/rpcecho,sign,seal]", + "ncacn_np:[,sign]", + "ncadg_ip_udp:", + "308FB580-1EB2-11CA-923B-08002B1075A7@ncacn_np:localhost", + "308FB580-1EB2-11CA-923B-08002B1075A7@ncacn_ip_tcp:127.0.0.1", +}; + BOOL torture_local_binding_string(int dummy) { BOOL ret = True; + TALLOC_CTX *mem_ctx = talloc_init("test_BindingString"); + int i; + + for (i = 0; i < ARRAY_SIZE(test_strings); i++) { + ret &= test_BindingString(mem_ctx, test_strings[i]); + } - ret &= test_BindingString("ncacn_np:"); - ret &= test_BindingString("ncalrpc:"); - ret &= test_BindingString("ncalrpc:"); - ret &= test_BindingString("ncacn_np:[rpcecho]"); - ret &= test_BindingString("ncacn_np:127.0.0.1[rpcecho]"); - ret &= test_BindingString("ncacn_np:localhost[rpcecho]"); - ret &= test_BindingString("ncacn_np:[/pipe/rpcecho]"); - ret &= test_BindingString("ncacn_np:localhost[/pipe/rpcecho,sign,seal]"); - ret &= test_BindingString("ncacn_np:[,sign]"); - ret &= test_BindingString("ncadg_ip_udp:"); - ret &= test_BindingString("308FB580-1EB2-11CA-923B-08002B1075A7@ncacn_np:localhost"); - ret &= test_BindingString("308FB580-1EB2-11CA-923B-08002B1075A7@ncacn_ip_tcp:localhost"); + talloc_destroy(mem_ctx); return ret; } |