summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/librpc/rpc/dcerpc_sock.c179
1 files changed, 135 insertions, 44 deletions
diff --git a/source4/librpc/rpc/dcerpc_sock.c b/source4/librpc/rpc/dcerpc_sock.c
index 838ddc628b..da48ae0f7d 100644
--- a/source4/librpc/rpc/dcerpc_sock.c
+++ b/source4/librpc/rpc/dcerpc_sock.c
@@ -27,6 +27,7 @@
#include "librpc/gen_ndr/ndr_epmapper.h"
#include "lib/socket/socket.h"
#include "lib/stream/packet.h"
+#include "libcli/composite/composite.h"
/* transport private information used by general socket pipe transports */
struct sock_private {
@@ -190,70 +191,73 @@ static const char *sock_peer_name(struct dcerpc_connection *p)
return sock->server_name;
}
-/*
- open a rpc connection using the generic socket library
-*/
-static NTSTATUS dcerpc_pipe_open_socket(struct dcerpc_connection *c,
- const char *server,
- uint32_t port,
- const char *type,
- enum dcerpc_transport_t transport)
-{
- struct sock_private *sock;
- struct socket_context *socket_ctx;
- NTSTATUS status;
- sock = talloc(c, struct sock_private);
- if (!sock) {
- return NT_STATUS_NO_MEMORY;
- }
+struct pipe_open_socket_state {
+ struct dcerpc_connection *conn;
+ struct socket_context *socket_ctx;
+ struct sock_private *sock;
+ const char *server;
+ uint32_t port;
+ enum dcerpc_transport_t transport;
+};
- status = socket_create(type, SOCKET_TYPE_STREAM, &socket_ctx, 0);
- if (!NT_STATUS_IS_OK(status)) {
- talloc_free(sock);
- return status;
- }
- talloc_steal(sock, socket_ctx);
- status = socket_connect_ev(socket_ctx, NULL, 0, server, port, 0, c->event_ctx);
- if (!NT_STATUS_IS_OK(status)) {
- talloc_free(sock);
- return status;
+static void continue_socket_connect(struct composite_context *ctx)
+{
+ struct dcerpc_connection *conn;
+ struct sock_private *sock;
+ struct composite_context *c = talloc_get_type(ctx->async.private_data,
+ struct composite_context);
+ struct pipe_open_socket_state *s = talloc_get_type(c->private_data,
+ struct pipe_open_socket_state);
+
+ /* make it easier to write a function calls */
+ conn = s->conn;
+ sock = s->sock;
+
+ c->status = socket_connect_recv(ctx);
+ if (!NT_STATUS_IS_OK(c->status)) {
+ DEBUG(0, ("Failed to connect host %s on port %d - %s\n", s->server, s->port,
+ nt_errstr(c->status)));
+ composite_error(c, c->status);
+ return;
}
/*
fill in the transport methods
*/
- c->transport.transport = transport;
- c->transport.private = NULL;
+ conn->transport.transport = s->transport;
+ conn->transport.private = NULL;
- c->transport.send_request = sock_send_request;
- c->transport.send_read = sock_send_read;
- c->transport.recv_data = NULL;
+ conn->transport.send_request = sock_send_request;
+ conn->transport.send_read = sock_send_read;
+ conn->transport.recv_data = NULL;
- c->transport.shutdown_pipe = sock_shutdown_pipe;
- c->transport.peer_name = sock_peer_name;
-
- sock->sock = socket_ctx;
- sock->pending_reads = 0;
- sock->server_name = strupper_talloc(sock, server);
+ conn->transport.shutdown_pipe = sock_shutdown_pipe;
+ conn->transport.peer_name = sock_peer_name;
- sock->fde = event_add_fd(c->event_ctx, sock->sock, socket_get_fd(sock->sock),
- 0, sock_io_handler, c);
+ sock->sock = s->socket_ctx;
+ sock->pending_reads = 0;
+ sock->server_name = strupper_talloc(sock, s->server);
- c->transport.private = sock;
+ sock->fde = event_add_fd(conn->event_ctx, sock->sock, socket_get_fd(sock->sock),
+ 0, sock_io_handler, conn);
+
+ conn->transport.private = sock;
sock->packet = packet_init(sock);
if (sock->packet == NULL) {
+ composite_error(c, NT_STATUS_NO_MEMORY);
talloc_free(sock);
- return NT_STATUS_NO_MEMORY;
+ return;
}
- packet_set_private(sock->packet, c);
+
+ packet_set_private(sock->packet, conn);
packet_set_socket(sock->packet, sock->sock);
packet_set_callback(sock->packet, sock_process_recv);
packet_set_full_request(sock->packet, sock_complete_packet);
packet_set_error_handler(sock->packet, sock_error_handler);
- packet_set_event_context(sock->packet, c->event_ctx);
+ packet_set_event_context(sock->packet, conn->event_ctx);
packet_set_fde(sock->packet, sock->fde);
packet_set_serialise(sock->packet);
packet_recv_disable(sock->packet);
@@ -262,9 +266,96 @@ static NTSTATUS dcerpc_pipe_open_socket(struct dcerpc_connection *c,
/* ensure we don't get SIGPIPE */
BlockSignals(True,SIGPIPE);
- return NT_STATUS_OK;
+ composite_done(c);
}
+
+struct composite_context *dcerpc_pipe_open_socket_send(TALLOC_CTX *mem_ctx,
+ struct dcerpc_connection *cn,
+ const char *server,
+ uint32_t port,
+ const char *type,
+ enum dcerpc_transport_t transport)
+{
+ NTSTATUS status;
+ struct composite_context *c;
+ struct pipe_open_socket_state *s;
+ struct composite_context *conn_req;
+
+ c = talloc_zero(mem_ctx, struct composite_context);
+ if (c == NULL) return NULL;
+
+ s = talloc_zero(c, struct pipe_open_socket_state);
+ if (s == NULL) {
+ composite_error(c, NT_STATUS_NO_MEMORY);
+ goto done;
+ }
+
+ c->state = COMPOSITE_STATE_IN_PROGRESS;
+ c->private_data = s;
+ c->event_ctx = cn->event_ctx;
+
+ s->conn = cn;
+ s->transport = transport;
+ s->port = port;
+ s->server = talloc_strdup(c, server);
+ if (s->server == NULL) {
+ composite_error(c, NT_STATUS_NO_MEMORY);
+ goto done;
+ }
+
+ s->sock = talloc(cn, struct sock_private);
+ if (s->sock == NULL) {
+ composite_error(c, NT_STATUS_NO_MEMORY);
+ goto done;
+ }
+
+ status = socket_create(type, SOCKET_TYPE_STREAM, &s->socket_ctx, 0);
+ if (!NT_STATUS_IS_OK(status)) {
+ composite_error(c, status);
+ talloc_free(s->sock);
+ goto done;
+ }
+ talloc_steal(s->sock, s->socket_ctx);
+
+ conn_req = socket_connect_send(s->socket_ctx, NULL, 0, s->server, s->port, 0, c->event_ctx);
+ if (conn_req == NULL) {
+ composite_error(c, NT_STATUS_NO_MEMORY);
+ goto done;
+ }
+
+ composite_continue(c, conn_req, continue_socket_connect, c);
+
+done:
+ return c;
+}
+
+
+NTSTATUS dcerpc_pipe_open_socket_recv(struct composite_context *c)
+{
+ NTSTATUS status = composite_wait(c);
+
+ talloc_free(c);
+ return status;
+}
+
+/*
+ open a rpc connection using the generic socket library
+*/
+NTSTATUS dcerpc_pipe_open_socket(struct dcerpc_connection *conn,
+ const char *server,
+ uint32_t port,
+ const char *type,
+ enum dcerpc_transport_t transport)
+{
+ struct composite_context *c;
+
+ c = dcerpc_pipe_open_socket_send(conn, conn, server, port,
+ type, transport);
+ return dcerpc_pipe_open_socket_recv(c);
+}
+
+
/*
open a rpc connection using tcp
*/