summaryrefslogtreecommitdiffstats
path: root/source4/librpc
diff options
context:
space:
mode:
authorSamuel Cabrero <samuelcabrero@kernevil.me>2014-09-16 17:01:02 +0200
committerStefan Metzmacher <metze@samba.org>2014-09-22 23:09:08 +0200
commit594d036afd78ae04b848607579707bcdced91ec3 (patch)
treedd05f82ccc984a26ba8ac46e7d7848dabc2a5ee6 /source4/librpc
parentd617230888840f0d89b1d30c851f5484c1f8182d (diff)
downloadsamba-594d036afd78ae04b848607579707bcdced91ec3.tar.gz
samba-594d036afd78ae04b848607579707bcdced91ec3.tar.xz
samba-594d036afd78ae04b848607579707bcdced91ec3.zip
ncacn_http: DCERPC pipe open using http transport
Signed-off-by: Samuel Cabrero <samuelcabrero@kernevil.me> Reviewed-by: Stefan Metzmacher <metze@samba.org> Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Diffstat (limited to 'source4/librpc')
-rw-r--r--source4/librpc/rpc/dcerpc_connect.c196
1 files changed, 196 insertions, 0 deletions
diff --git a/source4/librpc/rpc/dcerpc_connect.c b/source4/librpc/rpc/dcerpc_connect.c
index ecb5315038..fe3a0c8a62 100644
--- a/source4/librpc/rpc/dcerpc_connect.c
+++ b/source4/librpc/rpc/dcerpc_connect.c
@@ -403,6 +403,177 @@ static NTSTATUS dcerpc_pipe_connect_ncacn_ip_tcp_recv(struct composite_context *
}
+struct pipe_http_state {
+ struct dcerpc_pipe_connect io;
+ const char *localaddr;
+ const char *rpc_server;
+ uint32_t rpc_server_port;
+ char *rpc_proxy;
+ uint32_t rpc_proxy_port;
+ char *http_proxy;
+ uint32_t http_proxy_port;
+ bool use_tls;
+ bool use_proxy;
+ bool use_ntlm;
+ struct loadparm_context *lp_ctx;
+};
+
+/*
+ Stage 2 of ncacn_http: rpc pipe opened (or not)
+ */
+static void continue_pipe_open_ncacn_http(struct tevent_req *subreq)
+{
+ struct composite_context *c = NULL;
+ struct pipe_http_state *s = NULL;
+ struct tstream_context *stream = NULL;
+ struct tevent_queue *queue = NULL;
+
+ c = tevent_req_callback_data(subreq, struct composite_context);
+ s = talloc_get_type(c->private_data, struct pipe_http_state);
+
+ /* receive result of RoH connect request */
+ c->status = dcerpc_pipe_open_roh_recv(subreq, s->io.conn,
+ &stream, &queue);
+ TALLOC_FREE(subreq);
+ if (!composite_is_ok(c)) return;
+
+ s->io.conn->transport.transport = NCACN_HTTP;
+ s->io.conn->transport.stream = stream;
+ s->io.conn->transport.write_queue = queue;
+ s->io.conn->transport.pending_reads = 0;
+
+ composite_done(c);
+}
+
+/*
+ Initiate async open of a rpc connection to a rpc pipe using HTTP transport,
+ and using the binding structure to determine the endpoint and options
+*/
+static struct composite_context* dcerpc_pipe_connect_ncacn_http_send(
+ TALLOC_CTX *mem_ctx, struct dcerpc_pipe_connect *io,
+ struct loadparm_context *lp_ctx)
+{
+ struct composite_context *c;
+ struct pipe_http_state *s;
+ struct tevent_req *subreq;
+ const char *endpoint;
+ const char *use_proxy;
+ char *proxy;
+ char *port;
+ const char *opt;
+
+ /* composite context allocation and setup */
+ c = composite_create(mem_ctx, io->conn->event_ctx);
+ if (c == NULL) return NULL;
+
+ s = talloc_zero(c, struct pipe_http_state);
+ if (composite_nomem(s, c)) return c;
+ c->private_data = s;
+
+ /* store input parameters in state structure */
+ s->lp_ctx = lp_ctx;
+ s->io = *io;
+ s->localaddr = dcerpc_binding_get_string_option(io->binding,
+ "localaddress");
+ /* RPC server and port (the endpoint) */
+ s->rpc_server = dcerpc_binding_get_string_option(io->binding, "host");
+ endpoint = dcerpc_binding_get_string_option(io->binding, "endpoint");
+ if (endpoint == NULL) {
+ composite_error(c, NT_STATUS_INVALID_PARAMETER_MIX);
+ return c;
+ }
+ s->rpc_server_port = atoi(endpoint);
+ if (s->rpc_server_port == 0) {
+ composite_error(c, NT_STATUS_INVALID_PARAMETER_MIX);
+ return c;
+ }
+
+ /* Use TLS */
+ opt = dcerpc_binding_get_string_option(io->binding, "HttpUseTls");
+ if (opt) {
+ if (strcasecmp(opt, "true") == 0) {
+ s->use_tls = true;
+ } else if (strcasecmp(opt, "false") == 0) {
+ s->use_tls = false;
+ } else {
+ composite_error(c, NT_STATUS_INVALID_PARAMETER_MIX);
+ return c;
+ }
+ } else {
+ s->use_tls = true;
+ }
+
+ /* RPC Proxy */
+ proxy = port = talloc_strdup(s, dcerpc_binding_get_string_option(
+ io->binding, "RpcProxy"));
+ s->rpc_proxy = strsep(&port, ":");
+ if (proxy && port) {
+ s->rpc_proxy_port = atoi(port);
+ } else {
+ s->rpc_proxy_port = s->use_tls ? 443 : 80;
+ }
+ if (s->rpc_proxy == NULL) {
+ s->rpc_proxy = talloc_strdup(s, s->rpc_server);
+ if (composite_nomem(s->rpc_proxy, c)) return c;
+ }
+
+ /* HTTP Proxy */
+ proxy = port = talloc_strdup(s, dcerpc_binding_get_string_option(
+ io->binding, "HttpProxy"));
+ s->http_proxy = strsep(&port, ":");
+ if (proxy && port) {
+ s->http_proxy_port = atoi(port);
+ } else {
+ s->http_proxy_port = s->use_tls ? 443 : 80;
+ }
+
+ /* Use local proxy */
+ use_proxy = dcerpc_binding_get_string_option(io->binding,
+ "HttpConnectOption");
+ if (use_proxy && strcasecmp(use_proxy, "UseHttpProxy")) {
+ s->use_proxy = true;
+ }
+
+ /* If use local proxy set, the http proxy should be provided */
+ if (s->use_proxy && !s->http_proxy) {
+ composite_error(c, NT_STATUS_INVALID_PARAMETER_MIX);
+ return c;
+ }
+
+ /* Check which HTTP authentication method to use */
+ opt = dcerpc_binding_get_string_option(io->binding, "HttpAuthOption");
+ if (opt) {
+ if (strcasecmp(opt, "basic") == 0) {
+ s->use_ntlm = false;
+ } else if (strcasecmp(opt, "ntlm") == 0) {
+ s->use_ntlm = true;
+ } else {
+ composite_error(c, NT_STATUS_INVALID_PARAMETER_MIX);
+ return c;
+ }
+ } else {
+ s->use_ntlm = true;
+ }
+
+ subreq = dcerpc_pipe_open_roh_send(s->io.conn, s->localaddr,
+ s->rpc_server, s->rpc_server_port,
+ s->rpc_proxy, s->rpc_proxy_port,
+ s->http_proxy, s->http_proxy_port,
+ s->use_tls, s->use_proxy,
+ s->io.creds, io->resolve_ctx,
+ s->lp_ctx, s->use_ntlm);
+ if (composite_nomem(subreq, c)) return c;
+
+ tevent_req_set_callback(subreq, continue_pipe_open_ncacn_http, c);
+ return c;
+}
+
+static NTSTATUS dcerpc_pipe_connect_ncacn_http_recv(struct composite_context *c)
+{
+ return composite_wait_free(c);
+}
+
+
struct pipe_unix_state {
struct dcerpc_pipe_connect io;
const char *path;
@@ -559,6 +730,7 @@ static void continue_connect(struct composite_context *c, struct pipe_connect_st
static void continue_pipe_connect_ncacn_np_smb2(struct composite_context *ctx);
static void continue_pipe_connect_ncacn_np_smb(struct composite_context *ctx);
static void continue_pipe_connect_ncacn_ip_tcp(struct composite_context *ctx);
+static void continue_pipe_connect_ncacn_http(struct composite_context *ctx);
static void continue_pipe_connect_ncacn_unix(struct composite_context *ctx);
static void continue_pipe_connect_ncalrpc(struct composite_context *ctx);
static void continue_pipe_connect(struct composite_context *c, struct pipe_connect_state *s);
@@ -597,6 +769,7 @@ static void continue_connect(struct composite_context *c, struct pipe_connect_st
struct composite_context *ncacn_np_smb2_req;
struct composite_context *ncacn_np_smb_req;
struct composite_context *ncacn_ip_tcp_req;
+ struct composite_context *ncacn_http_req;
struct composite_context *ncacn_unix_req;
struct composite_context *ncalrpc_req;
enum dcerpc_transport_t transport;
@@ -635,6 +808,11 @@ static void continue_connect(struct composite_context *c, struct pipe_connect_st
composite_continue(c, ncacn_ip_tcp_req, continue_pipe_connect_ncacn_ip_tcp, c);
return;
+ case NCACN_HTTP:
+ ncacn_http_req = dcerpc_pipe_connect_ncacn_http_send(c, &pc, s->lp_ctx);
+ composite_continue(c, ncacn_http_req, continue_pipe_connect_ncacn_http, c);
+ return;
+
case NCACN_UNIX_STREAM:
ncacn_unix_req = dcerpc_pipe_connect_ncacn_unix_stream_send(c, &pc);
composite_continue(c, ncacn_unix_req, continue_pipe_connect_ncacn_unix, c);
@@ -710,6 +888,23 @@ static void continue_pipe_connect_ncacn_ip_tcp(struct composite_context *ctx)
/*
+ Stage 3 of pipe_connect_b: Receive result of pipe connect request on http
+*/
+static void continue_pipe_connect_ncacn_http(struct composite_context *ctx)
+{
+ struct composite_context *c = talloc_get_type(ctx->async.private_data,
+ struct composite_context);
+ struct pipe_connect_state *s = talloc_get_type(c->private_data,
+ struct pipe_connect_state);
+
+ c->status = dcerpc_pipe_connect_ncacn_http_recv(ctx);
+ if (!composite_is_ok(c)) return;
+
+ continue_pipe_connect(c, s);
+}
+
+
+/*
Stage 3 of pipe_connect_b: Receive result of pipe connect request on unix socket
*/
static void continue_pipe_connect_ncacn_unix(struct composite_context *ctx)
@@ -847,6 +1042,7 @@ _PUBLIC_ struct composite_context* dcerpc_pipe_connect_b_send(TALLOC_CTX *parent
switch (transport) {
case NCACN_NP:
case NCACN_IP_TCP:
+ case NCACN_HTTP:
case NCALRPC:
endpoint = dcerpc_binding_get_string_option(s->binding, "endpoint");
break;