/* 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);
{
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 */
/* 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 */
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;
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);
/*
- 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)
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;
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 */
*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);
}
} 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);
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;
*/
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 {
struct {
const char *name;
+ const char *address;
const char *binding;
const struct dcerpc_interface_table *dcerpc_iface;
} in;
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;
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
struct pipe_ip_tcp_state {
struct dcerpc_pipe_connect io;
const char *host;
+ const char *target_hostname;
uint32_t port;
};
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;
}
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;
}
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,
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);
}
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;
struct socket_context *socket_ctx;
struct sock_private *sock;
struct socket_address *server;
+ const char *target_hostname;
enum dcerpc_transport_t transport;
};
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);
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;
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;
*/
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;
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);
}
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;
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;
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;
}
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);
}
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;
}
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;
}
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;
/* 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);
}