mirror of
https://github.com/samba-team/samba.git
synced 2025-03-30 06:50:24 +03:00
Add unique IP address binding for client connections (EPM and ncacn_ip_tcp levels)
This allows for binding strings like this: ncacn_ip_tcp:host[localaddress=192.168.2.1,seal] which will force the connection to be locally bound to the specified IP address Signed-off-by: Andrew Tridgell <tridge@samba.org>
This commit is contained in:
parent
35aed17b26
commit
e5e5a1110f
@ -86,7 +86,8 @@ static const struct {
|
||||
{"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)
|
||||
@ -220,7 +221,12 @@ _PUBLIC_ char *dcerpc_binding_string(TALLOC_CTX *mem_ctx, const struct dcerpc_bi
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -313,6 +319,7 @@ _PUBLIC_ NTSTATUS dcerpc_parse_binding(TALLOC_CTX *mem_ctx, const char *s, struc
|
||||
b->flags = 0;
|
||||
b->assoc_group_id = 0;
|
||||
b->endpoint = NULL;
|
||||
b->localaddress = NULL;
|
||||
|
||||
if (!options) {
|
||||
*b_out = b;
|
||||
@ -339,8 +346,17 @@ _PUBLIC_ NTSTATUS dcerpc_parse_binding(TALLOC_CTX *mem_ctx, const char *s, struc
|
||||
/* 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];
|
||||
|
@ -41,6 +41,7 @@ struct dcerpc_binding {
|
||||
const char *target_hostname;
|
||||
const char *endpoint;
|
||||
const char **options;
|
||||
const char *localaddress;
|
||||
uint32_t flags;
|
||||
uint32_t assoc_group_id;
|
||||
};
|
||||
@ -95,6 +96,9 @@ struct dcerpc_binding {
|
||||
/* use NDR64 transport */
|
||||
#define DCERPC_NDR64 (1<<21)
|
||||
|
||||
/* specify binding interface */
|
||||
#define DCERPC_LOCALADDRESS (1<<22)
|
||||
|
||||
/* The following definitions come from librpc/rpc/binding.c */
|
||||
|
||||
const char *epm_floor_string(TALLOC_CTX *mem_ctx, struct epm_floor *epm_floor);
|
||||
|
@ -181,6 +181,9 @@ struct dcerpc_pipe {
|
||||
/* use NDR64 transport */
|
||||
#define DCERPC_NDR64 (1<<21)
|
||||
|
||||
/* specify binding interface */
|
||||
#define DCERPC_LOCALADDRESS (1<<22)
|
||||
|
||||
/* this describes a binding to a particular transport/pipe */
|
||||
struct dcerpc_binding {
|
||||
enum dcerpc_transport_t transport;
|
||||
@ -189,6 +192,7 @@ struct dcerpc_binding {
|
||||
const char *target_hostname;
|
||||
const char *endpoint;
|
||||
const char **options;
|
||||
const char *localaddress;
|
||||
uint32_t flags;
|
||||
uint32_t assoc_group_id;
|
||||
};
|
||||
|
@ -276,6 +276,7 @@ static NTSTATUS dcerpc_pipe_connect_ncacn_np_smb2_recv(struct composite_context
|
||||
|
||||
struct pipe_ip_tcp_state {
|
||||
struct dcerpc_pipe_connect io;
|
||||
const char *localaddr;
|
||||
const char *host;
|
||||
const char *target_hostname;
|
||||
uint32_t port;
|
||||
@ -319,13 +320,14 @@ static struct composite_context* dcerpc_pipe_connect_ncacn_ip_tcp_send(TALLOC_CT
|
||||
|
||||
/* store input parameters in state structure */
|
||||
s->io = *io;
|
||||
s->localaddr = talloc_reference(c, io->binding->localaddress);
|
||||
s->host = talloc_reference(c, io->binding->host);
|
||||
s->target_hostname = talloc_reference(c, io->binding->target_hostname);
|
||||
/* port number is a binding endpoint here */
|
||||
s->port = atoi(io->binding->endpoint);
|
||||
|
||||
/* send pipe open request on tcp/ip */
|
||||
pipe_req = dcerpc_pipe_open_tcp_send(s->io.pipe->conn, s->host, s->target_hostname,
|
||||
pipe_req = dcerpc_pipe_open_tcp_send(s->io.pipe->conn, s->localaddr, s->host, s->target_hostname,
|
||||
s->port, io->resolve_ctx);
|
||||
composite_continue(c, pipe_req, continue_pipe_open_ncacn_ip_tcp, c);
|
||||
return c;
|
||||
|
@ -102,6 +102,7 @@ _PUBLIC_ struct composite_context* dcerpc_secondary_connection_send(struct dcerp
|
||||
}
|
||||
|
||||
pipe_tcp_req = dcerpc_pipe_open_tcp_send(s->pipe2->conn,
|
||||
s->binding->localaddress,
|
||||
s->peer_addr->addr,
|
||||
s->binding->target_hostname,
|
||||
atoi(s->binding->endpoint),
|
||||
|
@ -228,6 +228,7 @@ struct pipe_open_socket_state {
|
||||
struct dcerpc_connection *conn;
|
||||
struct socket_context *socket_ctx;
|
||||
struct sock_private *sock;
|
||||
struct socket_address *localaddr;
|
||||
struct socket_address *server;
|
||||
const char *target_hostname;
|
||||
enum dcerpc_transport_t transport;
|
||||
@ -305,6 +306,7 @@ static void continue_socket_connect(struct composite_context *ctx)
|
||||
|
||||
static struct composite_context *dcerpc_pipe_open_socket_send(TALLOC_CTX *mem_ctx,
|
||||
struct dcerpc_connection *cn,
|
||||
struct socket_address *localaddr,
|
||||
struct socket_address *server,
|
||||
const char *target_hostname,
|
||||
const char *full_path,
|
||||
@ -323,6 +325,10 @@ static struct composite_context *dcerpc_pipe_open_socket_send(TALLOC_CTX *mem_ct
|
||||
|
||||
s->conn = cn;
|
||||
s->transport = transport;
|
||||
if (localaddr) {
|
||||
s->localaddr = talloc_reference(c, localaddr);
|
||||
if (composite_nomem(s->localaddr, c)) return c;
|
||||
}
|
||||
s->server = talloc_reference(c, server);
|
||||
if (composite_nomem(s->server, c)) return c;
|
||||
s->target_hostname = talloc_reference(s, target_hostname);
|
||||
@ -337,7 +343,7 @@ static struct composite_context *dcerpc_pipe_open_socket_send(TALLOC_CTX *mem_ct
|
||||
|
||||
s->sock->path = talloc_reference(s->sock, full_path);
|
||||
|
||||
conn_req = socket_connect_send(s->socket_ctx, NULL, s->server, 0,
|
||||
conn_req = socket_connect_send(s->socket_ctx, s->localaddr, s->server, 0,
|
||||
c->event_ctx);
|
||||
composite_continue(c, conn_req, continue_socket_connect, c);
|
||||
return c;
|
||||
@ -357,6 +363,7 @@ struct pipe_tcp_state {
|
||||
const char *target_hostname;
|
||||
const char *address;
|
||||
uint32_t port;
|
||||
struct socket_address *localaddr;
|
||||
struct socket_address *srvaddr;
|
||||
struct resolve_context *resolve_ctx;
|
||||
struct dcerpc_connection *conn;
|
||||
@ -385,7 +392,7 @@ static void continue_ip_resolve_name(struct composite_context *ctx)
|
||||
if (composite_nomem(s->srvaddr, c)) return;
|
||||
|
||||
/* resolve_nbt_name gives only ipv4 ... - send socket open request */
|
||||
sock_ipv4_req = dcerpc_pipe_open_socket_send(c, s->conn,
|
||||
sock_ipv4_req = dcerpc_pipe_open_socket_send(c, s->conn, s->localaddr,
|
||||
s->srvaddr, s->target_hostname,
|
||||
NULL,
|
||||
NCACN_IP_TCP);
|
||||
@ -419,7 +426,7 @@ static void continue_ipv6_open_socket(struct composite_context *ctx)
|
||||
if (composite_nomem(s->srvaddr, c)) return;
|
||||
|
||||
/* try IPv4 if IPv6 fails */
|
||||
sock_ipv4_req = dcerpc_pipe_open_socket_send(c, s->conn,
|
||||
sock_ipv4_req = dcerpc_pipe_open_socket_send(c, s->conn, s->localaddr,
|
||||
s->srvaddr, s->target_hostname,
|
||||
NCACN_IP_TCP);
|
||||
composite_continue(c, sock_ipv4_req, continue_ipv4_open_socket, c);
|
||||
@ -452,12 +459,12 @@ static void continue_ipv4_open_socket(struct composite_context *ctx)
|
||||
composite_done(c);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Send rpc pipe open request to given host:port using
|
||||
tcp/ip transport
|
||||
*/
|
||||
struct composite_context* dcerpc_pipe_open_tcp_send(struct dcerpc_connection *conn,
|
||||
const char *localaddr,
|
||||
const char *server,
|
||||
const char *target_hostname,
|
||||
uint32_t port,
|
||||
@ -486,6 +493,12 @@ struct composite_context* dcerpc_pipe_open_tcp_send(struct dcerpc_connection *co
|
||||
s->port = port;
|
||||
s->conn = conn;
|
||||
s->resolve_ctx = resolve_ctx;
|
||||
if (localaddr) {
|
||||
s->localaddr = socket_address_from_strings(s, "ip", localaddr, 0);
|
||||
/* if there is no localaddr, we pass NULL for
|
||||
s->localaddr, which is handled by the socket libraries as
|
||||
meaning no local binding address specified */
|
||||
}
|
||||
|
||||
make_nbt_name_server(&name, server);
|
||||
resolve_req = resolve_name_send(resolve_ctx, s, &name, c->event_ctx);
|
||||
@ -560,7 +573,7 @@ struct composite_context *dcerpc_pipe_open_unix_stream_send(struct dcerpc_connec
|
||||
if (composite_nomem(s->srvaddr, c)) return c;
|
||||
|
||||
/* send socket open request */
|
||||
sock_unix_req = dcerpc_pipe_open_socket_send(c, s->conn,
|
||||
sock_unix_req = dcerpc_pipe_open_socket_send(c, s->conn, NULL,
|
||||
s->srvaddr, NULL,
|
||||
s->path,
|
||||
NCALRPC);
|
||||
@ -631,7 +644,7 @@ struct composite_context* dcerpc_pipe_open_pipe_send(struct dcerpc_connection *c
|
||||
if (composite_nomem(s->srvaddr, c)) return c;
|
||||
|
||||
/* send socket open request */
|
||||
sock_np_req = dcerpc_pipe_open_socket_send(c, s->conn, s->srvaddr, NULL, s->path, NCALRPC);
|
||||
sock_np_req = dcerpc_pipe_open_socket_send(c, s->conn, NULL, s->srvaddr, NULL, s->path, NCALRPC);
|
||||
composite_continue(c, sock_np_req, continue_np_open_socket, c);
|
||||
return c;
|
||||
}
|
||||
|
@ -285,6 +285,7 @@ struct composite_context *dcerpc_epm_map_binding_send(TALLOC_CTX *mem_ctx,
|
||||
epmapper_binding->host = talloc_reference(epmapper_binding, binding->host);
|
||||
epmapper_binding->target_hostname = epmapper_binding->host;
|
||||
epmapper_binding->options = NULL;
|
||||
epmapper_binding->localaddress = talloc_reference(epmapper_binding, binding->localaddress);
|
||||
epmapper_binding->flags = 0;
|
||||
epmapper_binding->assoc_group_id = 0;
|
||||
epmapper_binding->endpoint = NULL;
|
||||
|
@ -128,6 +128,12 @@ static bool test_parse_check_results(struct torture_context *tctx)
|
||||
torture_assert_int_equal(tctx, b->object.if_version, 0, "object version");
|
||||
torture_assert_ntstatus_ok(tctx, dcerpc_parse_binding(tctx,
|
||||
"308FB580-1EB2-11CA-923B-08002B1075A7@ncacn_ip_tcp:$SERVER", &b), "parse");
|
||||
torture_assert_ntstatus_ok(tctx, dcerpc_parse_binding(tctx, "ncacn_ip_tcp:$SERVER[,sign,localaddress=192.168.1.1]", &b), "parse");
|
||||
torture_assert(tctx, b->transport == NCACN_IP_TCP, "ncacn_ip_tcp expected");
|
||||
torture_assert(tctx, b->flags == (DCERPC_SIGN | DCERPC_LOCALADDRESS), "sign flag");
|
||||
torture_assert_str_equal(tctx, b->localaddress, "192.168.1.1", "localaddress");
|
||||
torture_assert_str_equal(tctx, "ncacn_ip_tcp:$SERVER[,sign,localaddress=192.168.1.1]",
|
||||
dcerpc_binding_string(tctx, b), "back to string");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user