1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-11 05:18:09 +03:00

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>
This commit is contained in:
Samuel Cabrero 2014-09-16 17:01:02 +02:00 committed by Stefan Metzmacher
parent d617230888
commit 594d036afd

View File

@ -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);
@ -709,6 +887,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
*/
@ -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;