diff options
author | Samuel Cabrero <samuelcabrero@kernevil.me> | 2014-09-16 17:01:02 +0200 |
---|---|---|
committer | Stefan Metzmacher <metze@samba.org> | 2014-09-22 23:09:08 +0200 |
commit | 594d036afd78ae04b848607579707bcdced91ec3 (patch) | |
tree | dd05f82ccc984a26ba8ac46e7d7848dabc2a5ee6 /source4/librpc | |
parent | d617230888840f0d89b1d30c851f5484c1f8182d (diff) | |
download | samba-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.c | 196 |
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; |