diff options
-rw-r--r-- | source4/libnet/libnet_join.c | 2 | ||||
-rw-r--r-- | source4/libnet/libnet_rpc.c | 60 | ||||
-rw-r--r-- | source4/libnet/libnet_rpc.h | 19 | ||||
-rw-r--r-- | source4/librpc/rpc/dcerpc.h | 1 | ||||
-rw-r--r-- | source4/librpc/rpc/dcerpc_connect.c | 31 | ||||
-rw-r--r-- | source4/librpc/rpc/dcerpc_sock.c | 48 | ||||
-rw-r--r-- | source4/librpc/rpc/dcerpc_util.c | 3 | ||||
-rw-r--r-- | source4/torture/rpc/async_bind.c | 2 |
8 files changed, 102 insertions, 64 deletions
diff --git a/source4/libnet/libnet_join.c b/source4/libnet/libnet_join.c index 5781bc19c2..57ecddd9da 100644 --- a/source4/libnet/libnet_join.c +++ b/source4/libnet/libnet_join.c @@ -229,7 +229,7 @@ static NTSTATUS libnet_JoinADSDomain(struct libnet_context *ctx, struct libnet_J /* Now we know the user's DN, open with LDAP, read and modify a few things */ remote_ldb_url = talloc_asprintf(tmp_ctx, "ldap://%s", - drsuapi_binding->host); + drsuapi_binding->target_hostname); if (!remote_ldb_url) { r->out.error_string = NULL; talloc_free(tmp_ctx); diff --git a/source4/libnet/libnet_rpc.c b/source4/libnet/libnet_rpc.c index 53c8ba86a1..cedd0d07c0 100644 --- a/source4/libnet/libnet_rpc.c +++ b/source4/libnet/libnet_rpc.c @@ -53,6 +53,7 @@ static struct composite_context* libnet_RpcConnectSrv_send(struct libnet_context { struct composite_context *c; struct rpc_connect_srv_state *s; + struct dcerpc_binding *b; struct composite_context *pipe_connect_req; /* composite context allocation and setup */ @@ -72,16 +73,21 @@ static struct composite_context* libnet_RpcConnectSrv_send(struct libnet_context /* prepare binding string */ switch (r->level) { - case LIBNET_RPC_CONNECT_DC: - case LIBNET_RPC_CONNECT_PDC: case LIBNET_RPC_CONNECT_SERVER: s->binding = talloc_asprintf(s, "ncacn_np:%s", r->in.name); break; + case LIBNET_RPC_CONNECT_SERVER_ADDRESS: + s->binding = talloc_asprintf(s, "ncacn_np:%s", r->in.address); + break; case LIBNET_RPC_CONNECT_BINDING: s->binding = talloc_strdup(s, r->in.binding); break; + case LIBNET_RPC_CONNECT_DC: + case LIBNET_RPC_CONNECT_PDC: + /* this should never happen - DC and PDC level has a separate + composite function */ case LIBNET_RPC_CONNECT_DC_INFO: /* this should never happen - DC_INFO level has a separate composite function */ @@ -89,9 +95,23 @@ static struct composite_context* libnet_RpcConnectSrv_send(struct libnet_context return c; } + /* parse binding string to the structure */ + c->status = dcerpc_parse_binding(c, s->binding, &b); + if (!NT_STATUS_IS_OK(c->status)) { + DEBUG(0, ("Failed to parse dcerpc binding '%s'\n", s->binding)); + composite_error(c, c->status); + return c; + } + + if (r->level == LIBNET_RPC_CONNECT_SERVER_ADDRESS) { + b->target_hostname = talloc_reference(b, r->in.name); + if (composite_nomem(b->target_hostname, c)) { + return c; + } + } + /* connect to remote dcerpc pipe */ - pipe_connect_req = dcerpc_pipe_connect_send(c, &s->r.out.dcerpc_pipe, - s->binding, r->in.dcerpc_iface, + pipe_connect_req = dcerpc_pipe_connect_b_send(c, b, r->in.dcerpc_iface, ctx->cred, c->event_ctx); if (composite_nomem(pipe_connect_req, c)) return c; @@ -112,7 +132,7 @@ static void continue_pipe_connect(struct composite_context *ctx) s = talloc_get_type(c->private_data, struct rpc_connect_srv_state); /* receive result of rpc pipe connection */ - c->status = dcerpc_pipe_connect_recv(ctx, c, &s->r.out.dcerpc_pipe); + c->status = dcerpc_pipe_connect_b_recv(ctx, c, &s->r.out.dcerpc_pipe); s->r.out.error_string = NULL; composite_done(c); @@ -237,7 +257,7 @@ static struct composite_context* libnet_RpcConnectDC_send(struct libnet_context /* - Step 2 of RpcConnectDC: get domain controller name/address and + Step 2 of RpcConnectDC: get domain controller name and initiate RpcConnect to it */ static void continue_lookup_dc(struct composite_context *ctx) @@ -256,19 +276,7 @@ static void continue_lookup_dc(struct composite_context *ctx) if (!composite_is_ok(c)) return; /* decide on preferred address type depending on DC type */ - switch (s->r.level) { - case LIBNET_RPC_CONNECT_PDC: - s->connect_name = s->f.out.dcs[0].name; - break; - - case LIBNET_RPC_CONNECT_DC: - s->connect_name = s->f.out.dcs[0].address; - break; - - default: - /* we shouldn't absolutely get here */ - composite_error(c, NT_STATUS_INVALID_LEVEL); - } + s->connect_name = s->f.out.dcs[0].name; /* prepare a monitor message and post it */ msg.type = net_lookup_dc; @@ -282,11 +290,12 @@ static void continue_lookup_dc(struct composite_context *ctx) if (s->monitor_fn) s->monitor_fn(&msg); /* ok, pdc has been found so do attempt to rpc connect */ - s->r2.level = s->r.level; + s->r2.level = LIBNET_RPC_CONNECT_SERVER_ADDRESS; /* this will cause yet another name resolution, but at least * we pass the right name down the stack now */ - s->r2.in.name = talloc_strdup(c, s->connect_name); + s->r2.in.name = talloc_strdup(s, s->connect_name); + s->r2.in.address = talloc_steal(s, s->f.out.dcs[0].address); s->r2.in.dcerpc_iface = s->r.in.dcerpc_iface; /* send rpc connect request to the server */ @@ -630,7 +639,7 @@ static void continue_lsa_query_info(struct rpc_request *req) *s->final_binding = *s->lsa_pipe->binding; /* Ensure we keep hold of the member elements */ - talloc_reference(s->final_binding, s->lsa_pipe->binding); + if (composite_nomem(talloc_reference(s->final_binding, s->lsa_pipe->binding), c)) return; epm_map_req = dcerpc_epm_map_binding_send(c, s->final_binding, s->r.in.dcerpc_iface, s->lsa_pipe->conn->event_ctx); @@ -735,7 +744,11 @@ static NTSTATUS libnet_RpcConnectDCInfo_recv(struct composite_context *c, struct } } else { - r->out.error_string = talloc_steal(mem_ctx, s->r.out.error_string); + if (s->r.out.error_string) { + r->out.error_string = talloc_steal(mem_ctx, s->r.out.error_string); + } else { + r->out.error_string = talloc_asprintf(mem_ctx, "Connection to DC failed: %s", nt_errstr(status)); + } } talloc_free(c); @@ -761,6 +774,7 @@ struct composite_context* libnet_RpcConnect_send(struct libnet_context *ctx, switch (r->level) { case LIBNET_RPC_CONNECT_SERVER: + case LIBNET_RPC_CONNECT_SERVER_ADDRESS: case LIBNET_RPC_CONNECT_BINDING: c = libnet_RpcConnectSrv_send(ctx, mem_ctx, r); break; diff --git a/source4/libnet/libnet_rpc.h b/source4/libnet/libnet_rpc.h index 178e1cc269..2663cec869 100644 --- a/source4/libnet/libnet_rpc.h +++ b/source4/libnet/libnet_rpc.h @@ -26,14 +26,16 @@ */ enum libnet_RpcConnect_level { - LIBNET_RPC_CONNECT_SERVER, /* connect to a standalone rpc server */ - LIBNET_RPC_CONNECT_PDC, /* connect to a domain pdc (resolves domain - name to a pdc address before connecting) */ - LIBNET_RPC_CONNECT_DC, /* connect to any DC (resolves domain - name to a DC address before connecting) */ - LIBNET_RPC_CONNECT_BINDING, /* specified binding string */ - LIBNET_RPC_CONNECT_DC_INFO /* connect to a DC and provide basic domain - information (name, realm, sid, guid) */ + LIBNET_RPC_CONNECT_SERVER, /* connect to a standalone rpc server */ + LIBNET_RPC_CONNECT_SERVER_ADDRESS, /* connect to a standalone rpc server, + knowing both name and address */ + LIBNET_RPC_CONNECT_PDC, /* connect to a domain pdc (resolves domain + name to a pdc address before connecting) */ + LIBNET_RPC_CONNECT_DC, /* connect to any DC (resolves domain + name to a DC address before connecting) */ + LIBNET_RPC_CONNECT_BINDING, /* specified binding string */ + LIBNET_RPC_CONNECT_DC_INFO /* connect to a DC and provide basic domain + information (name, realm, sid, guid) */ }; struct libnet_RpcConnect { @@ -41,6 +43,7 @@ struct libnet_RpcConnect { struct { const char *name; + const char *address; const char *binding; const struct dcerpc_interface_table *dcerpc_iface; } in; diff --git a/source4/librpc/rpc/dcerpc.h b/source4/librpc/rpc/dcerpc.h index a609d17795..6bde842371 100644 --- a/source4/librpc/rpc/dcerpc.h +++ b/source4/librpc/rpc/dcerpc.h @@ -193,6 +193,7 @@ struct dcerpc_binding { enum dcerpc_transport_t transport; struct dcerpc_syntax_id object; const char *host; + const char *target_hostname; const char *endpoint; const char **options; uint32_t flags; diff --git a/source4/librpc/rpc/dcerpc_connect.c b/source4/librpc/rpc/dcerpc_connect.c index fba0ae0c02..c35da23f58 100644 --- a/source4/librpc/rpc/dcerpc_connect.c +++ b/source4/librpc/rpc/dcerpc_connect.c @@ -111,14 +111,11 @@ struct composite_context *dcerpc_pipe_connect_ncacn_np_smb_send(TALLOC_CTX *mem_ remote rpc server */ conn->in.dest_host = s->io.binding->host; conn->in.port = 0; - conn->in.called_name = strupper_talloc(mem_ctx, s->io.binding->host); + conn->in.called_name = s->io.binding->target_hostname; conn->in.service = "IPC$"; conn->in.service_type = NULL; conn->in.workgroup = lp_workgroup(); - /* verify if called_name has been allocated when uppercasing */ - if (composite_nomem(conn->in.called_name, c)) return c; - /* * provide proper credentials - user supplied, but allow a * fallback to anonymous if this is an schannel connection @@ -281,6 +278,7 @@ NTSTATUS dcerpc_pipe_connect_ncacn_np_smb2(TALLOC_CTX *mem_ctx, struct pipe_ip_tcp_state { struct dcerpc_pipe_connect io; const char *host; + const char *target_hostname; uint32_t port; }; @@ -321,12 +319,15 @@ struct composite_context* dcerpc_pipe_connect_ncacn_ip_tcp_send(TALLOC_CTX *mem_ c->private_data = s; /* store input parameters in state structure */ - s->io = *io; - s->host = talloc_strdup(c, io->binding->host); - s->port = atoi(io->binding->endpoint); /* port number is a binding endpoint here */ + s->io = *io; + 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->port); + pipe_req = dcerpc_pipe_open_tcp_send(s->io.pipe->conn, s->host, s->target_hostname, + s->port); composite_continue(c, pipe_req, continue_pipe_open_ncacn_ip_tcp, c); return c; } @@ -822,10 +823,11 @@ NTSTATUS dcerpc_pipe_connect_b_recv(struct composite_context *c, TALLOC_CTX *mem status = composite_wait(c); - s = talloc_get_type(c->private_data, struct pipe_connect_state); - talloc_steal(mem_ctx, s->pipe); - *p = s->pipe; - + if (NT_STATUS_IS_OK(status)) { + s = talloc_get_type(c->private_data, struct pipe_connect_state); + talloc_steal(mem_ctx, s->pipe); + *p = s->pipe; + } talloc_free(c); return status; } @@ -864,7 +866,6 @@ static void continue_pipe_connect_b(struct composite_context *ctx); The string is to be parsed to a binding structure first. */ struct composite_context* dcerpc_pipe_connect_send(TALLOC_CTX *parent_ctx, - struct dcerpc_pipe **pp, const char *binding, const struct dcerpc_interface_table *table, struct cli_credentials *credentials, @@ -966,7 +967,8 @@ NTSTATUS dcerpc_pipe_connect(TALLOC_CTX *parent_ctx, struct event_context *ev) { struct composite_context *c; - c = dcerpc_pipe_connect_send(parent_ctx, pp, binding, table, + c = dcerpc_pipe_connect_send(parent_ctx, binding, + table, credentials, ev); return dcerpc_pipe_connect_recv(c, parent_ctx, pp); } @@ -1032,6 +1034,7 @@ struct composite_context* dcerpc_secondary_connection_send(struct dcerpc_pipe *p case NCACN_IP_TCP: pipe_tcp_req = dcerpc_pipe_open_tcp_send(s->pipe2->conn, s->binding->host, + s->binding->target_hostname, atoi(s->binding->endpoint)); composite_continue(c, pipe_tcp_req, continue_open_tcp, c); return c; diff --git a/source4/librpc/rpc/dcerpc_sock.c b/source4/librpc/rpc/dcerpc_sock.c index 88e8381608..2cd6fcfb4c 100644 --- a/source4/librpc/rpc/dcerpc_sock.c +++ b/source4/librpc/rpc/dcerpc_sock.c @@ -206,6 +206,7 @@ struct pipe_open_socket_state { struct socket_context *socket_ctx; struct sock_private *sock; struct socket_address *server; + const char *target_hostname; enum dcerpc_transport_t transport; }; @@ -248,7 +249,7 @@ static void continue_socket_connect(struct composite_context *ctx) sock->sock = s->socket_ctx; sock->pending_reads = 0; - sock->server_name = strupper_talloc(sock, s->server->addr); + sock->server_name = strupper_talloc(sock, s->target_hostname); sock->fde = event_add_fd(conn->event_ctx, sock->sock, socket_get_fd(sock->sock), 0, sock_io_handler, conn); @@ -283,6 +284,7 @@ static void continue_socket_connect(struct composite_context *ctx) struct composite_context *dcerpc_pipe_open_socket_send(TALLOC_CTX *mem_ctx, struct dcerpc_connection *cn, struct socket_address *server, + const char *target_hostname, enum dcerpc_transport_t transport) { struct composite_context *c; @@ -300,6 +302,7 @@ struct composite_context *dcerpc_pipe_open_socket_send(TALLOC_CTX *mem_ctx, s->transport = transport; s->server = talloc_reference(c, server); if (composite_nomem(s->server, c)) return c; + s->target_hostname = talloc_reference(s, target_hostname); s->sock = talloc(cn, struct sock_private); if (composite_nomem(s->sock, c)) return c; @@ -328,17 +331,19 @@ NTSTATUS dcerpc_pipe_open_socket_recv(struct composite_context *c) */ NTSTATUS dcerpc_pipe_open_socket(struct dcerpc_connection *conn, struct socket_address *server, + const char *target_hostname, enum dcerpc_transport_t transport) { struct composite_context *c; - c = dcerpc_pipe_open_socket_send(conn, conn, server, transport); + c = dcerpc_pipe_open_socket_send(conn, conn, server, target_hostname, transport); return dcerpc_pipe_open_socket_recv(c); } struct pipe_tcp_state { - const char *server; + const char *target_hostname; + const char *address; uint32_t port; struct socket_address *srvaddr; struct dcerpc_connection *conn; @@ -371,11 +376,13 @@ void continue_ipv6_open_socket(struct composite_context *ctx) talloc_free(s->srvaddr); /* prepare server address using host:ip and transport name */ - s->srvaddr = socket_address_from_strings(s->conn, "ipv4", s->server, s->port); + s->srvaddr = socket_address_from_strings(s->conn, "ipv4", s->address, s->port); if (composite_nomem(s->srvaddr, c)) return; /* try IPv4 if IPv6 fails */ - sock_ipv4_req = dcerpc_pipe_open_socket_send(c, s->conn, s->srvaddr, NCACN_IP_TCP); + sock_ipv4_req = dcerpc_pipe_open_socket_send(c, s->conn, + s->srvaddr, s->target_hostname, + NCACN_IP_TCP); composite_continue(c, sock_ipv4_req, continue_ipv4_open_socket, c); } @@ -395,8 +402,9 @@ void continue_ipv4_open_socket(struct composite_context *ctx) c->status = dcerpc_pipe_open_socket_recv(ctx); if (!NT_STATUS_IS_OK(c->status)) { /* something went wrong... */ - DEBUG(0, ("Failed to connect host %s on port %d - %s.\n", - s->server, s->port, nt_errstr(c->status))); + DEBUG(0, ("Failed to connect host %s (%s) on port %d - %s.\n", + s->address, s->target_hostname, + s->port, nt_errstr(c->status))); composite_error(c, c->status); return; @@ -411,7 +419,9 @@ void continue_ipv4_open_socket(struct composite_context *ctx) tcp/ip transport */ struct composite_context* dcerpc_pipe_open_tcp_send(struct dcerpc_connection *conn, - const char* server, uint32_t port) + const char *address, + const char *target_hostname, + uint32_t port) { struct composite_context *c; struct composite_context *sock_ipv6_req; @@ -426,16 +436,19 @@ struct composite_context* dcerpc_pipe_open_tcp_send(struct dcerpc_connection *co c->private_data = s; /* store input parameters in state structure */ - s->server = talloc_strdup(c, server); - s->port = port; - s->conn = conn; + s->address = talloc_strdup(c, address); + s->target_hostname = talloc_strdup(c, target_hostname); + s->port = port; + s->conn = conn; /* prepare server address using host ip:port and transport name */ - s->srvaddr = socket_address_from_strings(s->conn, "ipv6", s->server, s->port); + s->srvaddr = socket_address_from_strings(s->conn, "ipv6", address, s->port); if (composite_nomem(s->srvaddr, c)) return c; /* try IPv6 first - send socket open request */ - sock_ipv6_req = dcerpc_pipe_open_socket_send(c, s->conn, s->srvaddr, NCACN_IP_TCP); + sock_ipv6_req = dcerpc_pipe_open_socket_send(c, s->conn, + s->srvaddr, s->target_hostname, + NCACN_IP_TCP); composite_continue(c, sock_ipv6_req, continue_ipv6_open_socket, c); return c; } @@ -458,11 +471,12 @@ NTSTATUS dcerpc_pipe_open_tcp_recv(struct composite_context *c) Open rpc pipe on tcp/ip transport - sync version */ NTSTATUS dcerpc_pipe_open_tcp(struct dcerpc_connection *conn, const char *server, + const char *target_hostname, uint32_t port) { struct composite_context *c; - c = dcerpc_pipe_open_tcp_send(conn, server, port); + c = dcerpc_pipe_open_tcp_send(conn, server, target_hostname, port); return dcerpc_pipe_open_tcp_recv(c); } @@ -521,7 +535,9 @@ 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, s->srvaddr, NCALRPC); + sock_unix_req = dcerpc_pipe_open_socket_send(c, s->conn, + s->srvaddr, NULL, + NCALRPC); composite_continue(c, sock_unix_req, continue_unix_open_socket, c); return c; } @@ -605,7 +621,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, NCALRPC); + sock_np_req = dcerpc_pipe_open_socket_send(c, s->conn, s->srvaddr, NULL, NCALRPC); composite_continue(c, sock_np_req, continue_np_open_socket, c); return c; } diff --git a/source4/librpc/rpc/dcerpc_util.c b/source4/librpc/rpc/dcerpc_util.c index 73e11f10f0..bdc0f8f6c5 100644 --- a/source4/librpc/rpc/dcerpc_util.c +++ b/source4/librpc/rpc/dcerpc_util.c @@ -358,11 +358,12 @@ NTSTATUS dcerpc_parse_binding(TALLOC_CTX *mem_ctx, const char *s, struct dcerpc_ b->host = talloc_strdup(b, s); options = NULL; } - if (!b->host) { return NT_STATUS_NO_MEMORY; } + b->target_hostname = b->host; + b->options = NULL; b->flags = 0; b->endpoint = NULL; diff --git a/source4/torture/rpc/async_bind.c b/source4/torture/rpc/async_bind.c index 18ed139ac7..952baacbf4 100644 --- a/source4/torture/rpc/async_bind.c +++ b/source4/torture/rpc/async_bind.c @@ -78,7 +78,7 @@ BOOL torture_async_bind(struct torture_context *torture) /* send bind requests */ for (i = 0; i < torture_numasync; i++) { table[i] = &dcerpc_table_lsarpc; - bind_req[i] = dcerpc_pipe_connect_send(mem_ctx, &pipe[i], binding_string, + bind_req[i] = dcerpc_pipe_connect_send(mem_ctx, binding_string, table[i], creds, evt_ctx); } |