From 6836f5d0b167027908da9a08b9b219520997b563 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 9 Jan 2005 08:34:05 +0000 Subject: r4616: the first phase in the addition of proper support for dcerpc_alter_context and multiple context_ids in the dcerpc client library. This stage does the following: - split "struct dcerpc_pipe" into two parts, the main part being "struct dcerpc_connection", which contains all the parts not dependent on the context, and "struct dcerpc_pipe" which has the context dependent part. This is similar to the layering in libcli_*() for SMB - disable the current dcerpc_alter code. I've used a #warning until i get the 2nd phase finished. I don't know how portable #warning is, but it won't be long before I add full alter context support anyway, so it won't last long - cleanup the allocation of dcerpc_pipe structures. The previous code was quite awkward. (This used to be commit 4004c69937be7e5dae56f9567ca607f982d395d3) --- source4/librpc/rpc/dcerpc.c | 382 +++++++++++++++++------------------ source4/librpc/rpc/dcerpc.h | 53 +++-- source4/librpc/rpc/dcerpc_auth.c | 84 ++++---- source4/librpc/rpc/dcerpc_ntlm.c | 17 +- source4/librpc/rpc/dcerpc_schannel.c | 40 ++-- source4/librpc/rpc/dcerpc_smb.c | 123 ++++++----- source4/librpc/rpc/dcerpc_sock.c | 67 +++--- source4/librpc/rpc/dcerpc_spnego.c | 27 ++- source4/librpc/rpc/dcerpc_util.c | 292 ++++++++++++++------------ 9 files changed, 560 insertions(+), 525 deletions(-) (limited to 'source4/librpc/rpc') diff --git a/source4/librpc/rpc/dcerpc.c b/source4/librpc/rpc/dcerpc.c index ee7250a4f9..a29e7f7b6b 100644 --- a/source4/librpc/rpc/dcerpc.c +++ b/source4/librpc/rpc/dcerpc.c @@ -3,7 +3,7 @@ raw dcerpc operations Copyright (C) Tim Potter 2003 - Copyright (C) Andrew Tridgell 2003 + Copyright (C) Andrew Tridgell 2003-2005 Copyright (C) Jelmer Vernooij 2004 This program is free software; you can redistribute it and/or modify @@ -25,8 +25,11 @@ #include "dlinklist.h" #include "librpc/gen_ndr/ndr_epmapper.h" -struct dcerpc_interface_list *dcerpc_pipes = NULL; +static struct dcerpc_interface_list *dcerpc_pipes = NULL; +/* + register a dcerpc client interface +*/ NTSTATUS librpc_register_interface(const struct dcerpc_interface_table *interface) { struct dcerpc_interface_list *l = talloc_p(talloc_autofree_context(), @@ -43,52 +46,92 @@ NTSTATUS librpc_register_interface(const struct dcerpc_interface_table *interfac return NT_STATUS_OK; } +/* + return the list of registered dcerpc_pipes +*/ +const struct dcerpc_interface_list *librpc_dcerpc_pipes(void) +{ + return dcerpc_pipes; +} + +/* destroy a dcerpc connection */ +static int dcerpc_connection_destructor(void *ptr) +{ + struct dcerpc_connection *c = ptr; + if (c->transport.shutdown_pipe) { + c->transport.shutdown_pipe(c); + } + return 0; +} + + +/* initialise a dcerpc connection. */ +struct dcerpc_connection *dcerpc_connection_init(TALLOC_CTX *mem_ctx) +{ + struct dcerpc_connection *c; + + c = talloc_zero(mem_ctx, struct dcerpc_connection); + if (!c) { + return NULL; + } + + c->call_id = 1; + c->security_state.auth_info = NULL; + c->security_state.session_key = dcerpc_generic_session_key; + c->security_state.generic_state = NULL; + c->binding_string = NULL; + c->flags = 0; + c->srv_max_xmit_frag = 0; + c->srv_max_recv_frag = 0; + c->pending = NULL; + + talloc_set_destructor(c, dcerpc_connection_destructor); + + return c; +} + /* initialise a dcerpc pipe. */ -struct dcerpc_pipe *dcerpc_pipe_init(void) +struct dcerpc_pipe *dcerpc_pipe_init(TALLOC_CTX *mem_ctx) { struct dcerpc_pipe *p; - p = talloc_p(NULL, struct dcerpc_pipe); + p = talloc_p(mem_ctx, struct dcerpc_pipe); if (!p) { return NULL; } - p->reference_count = 0; - p->call_id = 1; - p->security_state.auth_info = NULL; - p->security_state.session_key = dcerpc_generic_session_key; - p->security_state.generic_state = NULL; - p->binding_string = NULL; - p->flags = 0; - p->srv_max_xmit_frag = 0; - p->srv_max_recv_frag = 0; + p->conn = dcerpc_connection_init(p); + if (p->conn == NULL) { + talloc_free(p); + return NULL; + } + p->last_fault_code = 0; - p->pending = NULL; + p->context_id = 0; + + ZERO_STRUCT(p->syntax); + ZERO_STRUCT(p->transfer_syntax); return p; } + /* choose the next call id to use */ -static uint32_t next_call_id(struct dcerpc_pipe *p) +static uint32_t next_call_id(struct dcerpc_connection *c) { - p->call_id++; - if (p->call_id == 0) { - p->call_id++; + c->call_id++; + if (c->call_id == 0) { + c->call_id++; } - return p->call_id; + return c->call_id; } /* close down a dcerpc over SMB pipe */ void dcerpc_pipe_close(struct dcerpc_pipe *p) { - if (!p) return; - p->reference_count--; - if (p->reference_count <= 0) { - p->transport.shutdown_pipe(p); - talloc_free(p); - } + talloc_free(p); } /* we need to be able to get/set the fragment length without doing a full @@ -124,17 +167,18 @@ void dcerpc_set_auth_length(DATA_BLOB *blob, uint16_t v) /* setup for a ndr pull, also setting up any flags from the binding string */ -static struct ndr_pull *ndr_pull_init_flags(struct dcerpc_pipe *p, DATA_BLOB *blob, TALLOC_CTX *mem_ctx) +static struct ndr_pull *ndr_pull_init_flags(struct dcerpc_connection *c, + DATA_BLOB *blob, TALLOC_CTX *mem_ctx) { struct ndr_pull *ndr = ndr_pull_init_blob(blob, mem_ctx); if (ndr == NULL) return ndr; - if (p->flags & DCERPC_DEBUG_PAD_CHECK) { + if (c->flags & DCERPC_DEBUG_PAD_CHECK) { ndr->flags |= LIBNDR_FLAG_PAD_CHECK; } - if (p->flags & DCERPC_NDR_REF_ALLOC) { + if (c->flags & DCERPC_NDR_REF_ALLOC) { ndr->flags |= LIBNDR_FLAG_REF_ALLOC; } @@ -145,12 +189,12 @@ static struct ndr_pull *ndr_pull_init_flags(struct dcerpc_pipe *p, DATA_BLOB *bl parse a data blob into a dcerpc_packet structure. This handles both input and output packets */ -static NTSTATUS dcerpc_pull(struct dcerpc_pipe *p, DATA_BLOB *blob, TALLOC_CTX *mem_ctx, +static NTSTATUS dcerpc_pull(struct dcerpc_connection *c, DATA_BLOB *blob, TALLOC_CTX *mem_ctx, struct dcerpc_packet *pkt) { struct ndr_pull *ndr; - ndr = ndr_pull_init_flags(p, blob, mem_ctx); + ndr = ndr_pull_init_flags(c, blob, mem_ctx); if (!ndr) { return NT_STATUS_NO_MEMORY; } @@ -177,7 +221,7 @@ static NTSTATUS dcerpc_connect_verifier(TALLOC_CTX *mem_ctx, DATA_BLOB *blob) } /* - generate a CONNECT level verifier + check a CONNECT level verifier */ static NTSTATUS dcerpc_check_connect_verifier(DATA_BLOB *blob) { @@ -191,7 +235,7 @@ static NTSTATUS dcerpc_check_connect_verifier(DATA_BLOB *blob) /* parse a possibly signed blob into a dcerpc request packet structure */ -static NTSTATUS dcerpc_pull_request_sign(struct dcerpc_pipe *p, +static NTSTATUS dcerpc_pull_request_sign(struct dcerpc_connection *c, DATA_BLOB *blob, TALLOC_CTX *mem_ctx, struct dcerpc_packet *pkt) { @@ -201,12 +245,12 @@ static NTSTATUS dcerpc_pull_request_sign(struct dcerpc_pipe *p, DATA_BLOB auth_blob; /* non-signed packets are simpler */ - if (!p->security_state.auth_info || - !p->security_state.generic_state) { - return dcerpc_pull(p, blob, mem_ctx, pkt); + if (!c->security_state.auth_info || + !c->security_state.generic_state) { + return dcerpc_pull(c, blob, mem_ctx, pkt); } - ndr = ndr_pull_init_flags(p, blob, mem_ctx); + ndr = ndr_pull_init_flags(c, blob, mem_ctx); if (!ndr) { return NT_STATUS_NO_MEMORY; } @@ -226,7 +270,7 @@ static NTSTATUS dcerpc_pull_request_sign(struct dcerpc_pipe *p, } if (pkt->auth_length == 0 && - p->security_state.auth_info->auth_level == DCERPC_AUTH_LEVEL_CONNECT) { + c->security_state.auth_info->auth_level == DCERPC_AUTH_LEVEL_CONNECT) { return NT_STATUS_OK; } @@ -243,7 +287,7 @@ static NTSTATUS dcerpc_pull_request_sign(struct dcerpc_pipe *p, pkt->u.response.stub_and_verifier.length -= auth_blob.length; /* pull the auth structure */ - ndr = ndr_pull_init_flags(p, &auth_blob, mem_ctx); + ndr = ndr_pull_init_flags(c, &auth_blob, mem_ctx); if (!ndr) { return NT_STATUS_NO_MEMORY; } @@ -259,9 +303,9 @@ static NTSTATUS dcerpc_pull_request_sign(struct dcerpc_pipe *p, /* check signature or unseal the packet */ - switch (p->security_state.auth_info->auth_level) { + switch (c->security_state.auth_info->auth_level) { case DCERPC_AUTH_LEVEL_PRIVACY: - status = gensec_unseal_packet(p->security_state.generic_state, + status = gensec_unseal_packet(c->security_state.generic_state, mem_ctx, blob->data + DCERPC_REQUEST_LENGTH, pkt->u.response.stub_and_verifier.length, @@ -274,7 +318,7 @@ static NTSTATUS dcerpc_pull_request_sign(struct dcerpc_pipe *p, break; case DCERPC_AUTH_LEVEL_INTEGRITY: - status = gensec_check_packet(p->security_state.generic_state, + status = gensec_check_packet(c->security_state.generic_state, mem_ctx, pkt->u.response.stub_and_verifier.data, pkt->u.response.stub_and_verifier.length, @@ -308,7 +352,7 @@ static NTSTATUS dcerpc_pull_request_sign(struct dcerpc_pipe *p, /* push a dcerpc request packet into a blob, possibly signing it. */ -static NTSTATUS dcerpc_push_request_sign(struct dcerpc_pipe *p, +static NTSTATUS dcerpc_push_request_sign(struct dcerpc_connection *c, DATA_BLOB *blob, TALLOC_CTX *mem_ctx, struct dcerpc_packet *pkt) { @@ -317,9 +361,9 @@ static NTSTATUS dcerpc_push_request_sign(struct dcerpc_pipe *p, DATA_BLOB creds2; /* non-signed packets are simpler */ - if (!p->security_state.auth_info || - !p->security_state.generic_state) { - return dcerpc_push_auth(blob, mem_ctx, pkt, p->security_state.auth_info); + if (!c->security_state.auth_info || + !c->security_state.generic_state) { + return dcerpc_push_auth(blob, mem_ctx, pkt, c->security_state.auth_info); } ndr = ndr_push_init_ctx(mem_ctx); @@ -327,7 +371,7 @@ static NTSTATUS dcerpc_push_request_sign(struct dcerpc_pipe *p, return NT_STATUS_NO_MEMORY; } - if (p->flags & DCERPC_PUSH_BIGENDIAN) { + if (c->flags & DCERPC_PUSH_BIGENDIAN) { ndr->flags |= LIBNDR_FLAG_BIGENDIAN; } @@ -342,25 +386,25 @@ static NTSTATUS dcerpc_push_request_sign(struct dcerpc_pipe *p, /* pad to 16 byte multiple in the payload portion of the packet. This matches what w2k3 does */ - p->security_state.auth_info->auth_pad_length = + c->security_state.auth_info->auth_pad_length = (16 - (pkt->u.request.stub_and_verifier.length & 15)) & 15; - ndr_push_zero(ndr, p->security_state.auth_info->auth_pad_length); + ndr_push_zero(ndr, c->security_state.auth_info->auth_pad_length); /* sign or seal the packet */ - switch (p->security_state.auth_info->auth_level) { + switch (c->security_state.auth_info->auth_level) { case DCERPC_AUTH_LEVEL_PRIVACY: case DCERPC_AUTH_LEVEL_INTEGRITY: - p->security_state.auth_info->credentials - = data_blob_talloc(mem_ctx, NULL, gensec_sig_size(p->security_state.generic_state)); - data_blob_clear(&p->security_state.auth_info->credentials); + c->security_state.auth_info->credentials + = data_blob_talloc(mem_ctx, NULL, gensec_sig_size(c->security_state.generic_state)); + data_blob_clear(&c->security_state.auth_info->credentials); break; case DCERPC_AUTH_LEVEL_CONNECT: - status = dcerpc_connect_verifier(mem_ctx, &p->security_state.auth_info->credentials); + status = dcerpc_connect_verifier(mem_ctx, &c->security_state.auth_info->credentials); break; case DCERPC_AUTH_LEVEL_NONE: - p->security_state.auth_info->credentials = data_blob(NULL, 0); + c->security_state.auth_info->credentials = data_blob(NULL, 0); break; default: @@ -373,7 +417,7 @@ static NTSTATUS dcerpc_push_request_sign(struct dcerpc_pipe *p, } /* add the auth verifier */ - status = ndr_push_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, p->security_state.auth_info); + status = ndr_push_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, c->security_state.auth_info); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -385,18 +429,19 @@ static NTSTATUS dcerpc_push_request_sign(struct dcerpc_pipe *p, in these earlier as we don't know the signature length (it could be variable length) */ dcerpc_set_frag_length(blob, blob->length); - dcerpc_set_auth_length(blob, p->security_state.auth_info->credentials.length); + dcerpc_set_auth_length(blob, c->security_state.auth_info->credentials.length); /* sign or seal the packet */ - switch (p->security_state.auth_info->auth_level) { + switch (c->security_state.auth_info->auth_level) { case DCERPC_AUTH_LEVEL_PRIVACY: - status = gensec_seal_packet(p->security_state.generic_state, + status = gensec_seal_packet(c->security_state.generic_state, mem_ctx, blob->data + DCERPC_REQUEST_LENGTH, - pkt->u.request.stub_and_verifier.length+p->security_state.auth_info->auth_pad_length, + pkt->u.request.stub_and_verifier.length + + c->security_state.auth_info->auth_pad_length, blob->data, blob->length - - p->security_state.auth_info->credentials.length, + c->security_state.auth_info->credentials.length, &creds2); if (!NT_STATUS_IS_OK(status)) { return status; @@ -405,13 +450,14 @@ static NTSTATUS dcerpc_push_request_sign(struct dcerpc_pipe *p, break; case DCERPC_AUTH_LEVEL_INTEGRITY: - status = gensec_sign_packet(p->security_state.generic_state, + status = gensec_sign_packet(c->security_state.generic_state, mem_ctx, blob->data + DCERPC_REQUEST_LENGTH, - pkt->u.request.stub_and_verifier.length+p->security_state.auth_info->auth_pad_length, + pkt->u.request.stub_and_verifier.length + + c->security_state.auth_info->auth_pad_length, blob->data, blob->length - - p->security_state.auth_info->credentials.length, + c->security_state.auth_info->credentials.length, &creds2); if (!NT_STATUS_IS_OK(status)) { return status; @@ -423,7 +469,7 @@ static NTSTATUS dcerpc_push_request_sign(struct dcerpc_pipe *p, break; case DCERPC_AUTH_LEVEL_NONE: - p->security_state.auth_info->credentials = data_blob(NULL, 0); + c->security_state.auth_info->credentials = data_blob(NULL, 0); break; default: @@ -431,7 +477,7 @@ static NTSTATUS dcerpc_push_request_sign(struct dcerpc_pipe *p, break; } - data_blob_free(&p->security_state.auth_info->credentials); + data_blob_free(&c->security_state.auth_info->credentials); return NT_STATUS_OK; } @@ -440,11 +486,11 @@ static NTSTATUS dcerpc_push_request_sign(struct dcerpc_pipe *p, /* fill in the fixed values in a dcerpc header */ -static void init_dcerpc_hdr(struct dcerpc_pipe *p, struct dcerpc_packet *pkt) +static void init_dcerpc_hdr(struct dcerpc_connection *c, struct dcerpc_packet *pkt) { pkt->rpc_vers = 5; pkt->rpc_vers_minor = 0; - if (p->flags & DCERPC_PUSH_BIGENDIAN) { + if (c->flags & DCERPC_PUSH_BIGENDIAN) { pkt->drep[0] = 0; } else { pkt->drep[0] = DCERPC_DREP_LE; @@ -465,10 +511,10 @@ struct full_request_state { /* receive a reply to a full request */ -static void full_request_recv(struct dcerpc_pipe *p, DATA_BLOB *blob, +static void full_request_recv(struct dcerpc_connection *c, DATA_BLOB *blob, NTSTATUS status) { - struct full_request_state *state = p->full_request_private; + struct full_request_state *state = c->full_request_private; if (!NT_STATUS_IS_OK(status)) { state->status = status; @@ -482,7 +528,7 @@ static void full_request_recv(struct dcerpc_pipe *p, DATA_BLOB *blob, perform a single pdu synchronous request - used for the bind code this cannot be mixed with normal async requests */ -static NTSTATUS full_request(struct dcerpc_pipe *p, +static NTSTATUS full_request(struct dcerpc_connection *c, TALLOC_CTX *mem_ctx, DATA_BLOB *request_blob, DATA_BLOB *reply_blob) @@ -497,16 +543,16 @@ static NTSTATUS full_request(struct dcerpc_pipe *p, state->reply_blob = reply_blob; state->status = NT_STATUS_OK; - p->transport.recv_data = full_request_recv; - p->full_request_private = state; + c->transport.recv_data = full_request_recv; + c->full_request_private = state; - status = p->transport.send_request(p, request_blob, True); + status = c->transport.send_request(c, request_blob, True); if (!NT_STATUS_IS_OK(status)) { return status; } while (NT_STATUS_IS_OK(state->status) && state->reply_blob) { - struct event_context *ctx = p->transport.event_context(p); + struct event_context *ctx = c->transport.event_context(c); if (event_loop_once(ctx) != 0) { return NT_STATUS_CONNECTION_DISCONNECTED; } @@ -534,41 +580,41 @@ NTSTATUS dcerpc_bind(struct dcerpc_pipe *p, p->syntax = *syntax; p->transfer_syntax = *transfer_syntax; - init_dcerpc_hdr(p, &pkt); + init_dcerpc_hdr(p->conn, &pkt); pkt.ptype = DCERPC_PKT_BIND; pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST; - pkt.call_id = p->call_id; + pkt.call_id = p->conn->call_id; pkt.auth_length = 0; pkt.u.bind.max_xmit_frag = 5840; pkt.u.bind.max_recv_frag = 5840; pkt.u.bind.assoc_group_id = 0; pkt.u.bind.num_contexts = 1; - pkt.u.bind.ctx_list = talloc_p(mem_ctx, struct dcerpc_ctx_list); + pkt.u.bind.ctx_list = talloc_array(mem_ctx, struct dcerpc_ctx_list, 1); if (!pkt.u.bind.ctx_list) { return NT_STATUS_NO_MEMORY; } - pkt.u.bind.ctx_list[0].context_id = 0; + pkt.u.bind.ctx_list[0].context_id = p->context_id; pkt.u.bind.ctx_list[0].num_transfer_syntaxes = 1; pkt.u.bind.ctx_list[0].abstract_syntax = p->syntax; pkt.u.bind.ctx_list[0].transfer_syntaxes = &p->transfer_syntax; pkt.u.bind.auth_info = data_blob(NULL, 0); /* construct the NDR form of the packet */ - status = dcerpc_push_auth(&blob, mem_ctx, &pkt, p->security_state.auth_info); + status = dcerpc_push_auth(&blob, mem_ctx, &pkt, p->conn->security_state.auth_info); if (!NT_STATUS_IS_OK(status)) { return status; } /* send it on its way */ - status = full_request(p, mem_ctx, &blob, &blob); + status = full_request(p->conn, mem_ctx, &blob, &blob); if (!NT_STATUS_IS_OK(status)) { return status; } /* unmarshall the NDR */ - status = dcerpc_pull(p, &blob, mem_ctx, &pkt); + status = dcerpc_pull(p->conn, &blob, mem_ctx, &pkt); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -585,117 +631,49 @@ NTSTATUS dcerpc_bind(struct dcerpc_pipe *p, } if (pkt.ptype == DCERPC_PKT_BIND_ACK) { - p->srv_max_xmit_frag = pkt.u.bind_ack.max_xmit_frag; - p->srv_max_recv_frag = pkt.u.bind_ack.max_recv_frag; + p->conn->srv_max_xmit_frag = pkt.u.bind_ack.max_xmit_frag; + p->conn->srv_max_recv_frag = pkt.u.bind_ack.max_recv_frag; } /* the bind_ack might contain a reply set of credentials */ - if (p->security_state.auth_info && pkt.u.bind_ack.auth_info.length) { + if (p->conn->security_state.auth_info && pkt.u.bind_ack.auth_info.length) { status = ndr_pull_struct_blob(&pkt.u.bind_ack.auth_info, mem_ctx, - p->security_state.auth_info, + p->conn->security_state.auth_info, (ndr_pull_flags_fn_t)ndr_pull_dcerpc_auth); } return status; } -/* - perform a alter context using the given syntax - - the auth_info structure is updated with the reply authentication info - on success -*/ -NTSTATUS dcerpc_alter(struct dcerpc_pipe *p, - TALLOC_CTX *mem_ctx) -{ - struct dcerpc_packet pkt; - NTSTATUS status; - DATA_BLOB blob; - - init_dcerpc_hdr(p, &pkt); - - pkt.ptype = DCERPC_PKT_ALTER; - pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST; - pkt.call_id = p->call_id; - pkt.auth_length = 0; - - pkt.u.alter.max_xmit_frag = 0x2000; - pkt.u.alter.max_recv_frag = 0x2000; - pkt.u.alter.assoc_group_id = 0; - pkt.u.alter.num_contexts = 1; - pkt.u.alter.ctx_list = talloc_p(mem_ctx, struct dcerpc_ctx_list); - if (!pkt.u.alter.ctx_list) { - return NT_STATUS_NO_MEMORY; - } - pkt.u.alter.ctx_list[0].context_id = 0; - pkt.u.alter.ctx_list[0].num_transfer_syntaxes = 1; - pkt.u.alter.ctx_list[0].abstract_syntax = p->syntax; - pkt.u.alter.ctx_list[0].transfer_syntaxes = &p->transfer_syntax; - pkt.u.alter.auth_info = data_blob(NULL, 0); - - /* construct the NDR form of the packet */ - status = dcerpc_push_auth(&blob, mem_ctx, &pkt, p->security_state.auth_info); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - /* send it on its way */ - status = full_request(p, mem_ctx, &blob, &blob); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - /* unmarshall the NDR */ - status = dcerpc_pull(p, &blob, mem_ctx, &pkt); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - if ((pkt.ptype != DCERPC_PKT_ALTER_ACK) || - pkt.u.alter_ack.num_results == 0 || - pkt.u.alter_ack.ctx_list[0].result != 0) { - status = NT_STATUS_UNSUCCESSFUL; - } - - /* the bind_ack might contain a reply set of credentials */ - if (p->security_state.auth_info && pkt.u.alter_ack.auth_info.length) { - status = ndr_pull_struct_blob(&pkt.u.alter_ack.auth_info, - mem_ctx, - p->security_state.auth_info, - (ndr_pull_flags_fn_t)ndr_pull_dcerpc_auth); - } - - return status; -} /* perform a continued bind (and auth3) */ -NTSTATUS dcerpc_auth3(struct dcerpc_pipe *p, +NTSTATUS dcerpc_auth3(struct dcerpc_connection *c, TALLOC_CTX *mem_ctx) { struct dcerpc_packet pkt; NTSTATUS status; DATA_BLOB blob; - init_dcerpc_hdr(p, &pkt); + init_dcerpc_hdr(c, &pkt); pkt.ptype = DCERPC_PKT_AUTH3; pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST; - pkt.call_id = next_call_id(p); + pkt.call_id = next_call_id(c); pkt.auth_length = 0; pkt.u.auth3._pad = 0; pkt.u.auth3.auth_info = data_blob(NULL, 0); /* construct the NDR form of the packet */ - status = dcerpc_push_auth(&blob, mem_ctx, &pkt, p->security_state.auth_info); + status = dcerpc_push_auth(&blob, mem_ctx, &pkt, c->security_state.auth_info); if (!NT_STATUS_IS_OK(status)) { return status; } /* send it on its way */ - status = p->transport.send_request(p, &blob, False); + status = c->transport.send_request(c, &blob, False); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -733,7 +711,7 @@ NTSTATUS dcerpc_bind_byuuid(struct dcerpc_pipe *p, process a fragment received from the transport layer during a request */ -static void dcerpc_request_recv_data(struct dcerpc_pipe *p, +static void dcerpc_request_recv_data(struct dcerpc_connection *c, DATA_BLOB *data, NTSTATUS status) { @@ -743,11 +721,11 @@ static void dcerpc_request_recv_data(struct dcerpc_pipe *p, if (!NT_STATUS_IS_OK(status)) { /* all pending requests get the error */ - while (p->pending) { - req = p->pending; + while (c->pending) { + req = c->pending; req->state = RPC_REQUEST_DONE; req->status = status; - DLIST_REMOVE(p->pending, req); + DLIST_REMOVE(c->pending, req); if (req->async.callback) { req->async.callback(req); } @@ -757,12 +735,12 @@ static void dcerpc_request_recv_data(struct dcerpc_pipe *p, pkt.call_id = 0; - status = dcerpc_pull_request_sign(p, data, (TALLOC_CTX *)data->data, &pkt); + status = dcerpc_pull_request_sign(c, data, (TALLOC_CTX *)data->data, &pkt); /* find the matching request. Notice we match before we check the status. this is ok as a pending call_id can never be zero */ - for (req=p->pending;req;req=req->next) { + for (req=c->pending;req;req=req->next) { if (pkt.call_id == req->call_id) break; } @@ -774,7 +752,7 @@ static void dcerpc_request_recv_data(struct dcerpc_pipe *p, if (!NT_STATUS_IS_OK(status)) { req->status = status; req->state = RPC_REQUEST_DONE; - DLIST_REMOVE(p->pending, req); + DLIST_REMOVE(c->pending, req); if (req->async.callback) { req->async.callback(req); } @@ -782,11 +760,11 @@ static void dcerpc_request_recv_data(struct dcerpc_pipe *p, } if (pkt.ptype == DCERPC_PKT_FAULT) { - DEBUG(5,("rpc fault: %s\n", dcerpc_errstr(p, pkt.u.fault.status))); + DEBUG(5,("rpc fault: %s\n", dcerpc_errstr(c, pkt.u.fault.status))); req->fault_code = pkt.u.fault.status; req->status = NT_STATUS_NET_WRITE_FAULT; req->state = RPC_REQUEST_DONE; - DLIST_REMOVE(p->pending, req); + DLIST_REMOVE(c->pending, req); if (req->async.callback) { req->async.callback(req); } @@ -799,7 +777,7 @@ static void dcerpc_request_recv_data(struct dcerpc_pipe *p, req->fault_code = DCERPC_FAULT_OTHER; req->status = NT_STATUS_NET_WRITE_FAULT; req->state = RPC_REQUEST_DONE; - DLIST_REMOVE(p->pending, req); + DLIST_REMOVE(c->pending, req); if (req->async.callback) { req->async.callback(req); } @@ -816,7 +794,7 @@ static void dcerpc_request_recv_data(struct dcerpc_pipe *p, if (!req->payload.data) { req->status = NT_STATUS_NO_MEMORY; req->state = RPC_REQUEST_DONE; - DLIST_REMOVE(p->pending, req); + DLIST_REMOVE(c->pending, req); if (req->async.callback) { req->async.callback(req); } @@ -828,13 +806,13 @@ static void dcerpc_request_recv_data(struct dcerpc_pipe *p, } if (!(pkt.pfc_flags & DCERPC_PFC_FLAG_LAST)) { - p->transport.send_read(p); + c->transport.send_read(c); return; } /* we've got the full payload */ req->state = RPC_REQUEST_DONE; - DLIST_REMOVE(p->pending, req); + DLIST_REMOVE(c->pending, req); if (!(pkt.drep[0] & DCERPC_DREP_LE)) { req->flags |= DCERPC_PULL_BIGENDIAN; @@ -854,12 +832,12 @@ static void dcerpc_request_recv_data(struct dcerpc_pipe *p, static int dcerpc_req_destructor(void *ptr) { struct rpc_request *req = ptr; - DLIST_REMOVE(req->p->pending, req); + DLIST_REMOVE(req->p->conn->pending, req); return 0; } /* - perform the send size of a async dcerpc request + perform the send side of a async dcerpc request */ struct rpc_request *dcerpc_request_send(struct dcerpc_pipe *p, const struct GUID *object, @@ -873,7 +851,7 @@ struct rpc_request *dcerpc_request_send(struct dcerpc_pipe *p, uint32_t remaining, chunk_size; BOOL first_packet = True; - p->transport.recv_data = dcerpc_request_recv_data; + p->conn->transport.recv_data = dcerpc_request_recv_data; req = talloc_p(mem_ctx, struct rpc_request); if (req == NULL) { @@ -881,7 +859,7 @@ struct rpc_request *dcerpc_request_send(struct dcerpc_pipe *p, } req->p = p; - req->call_id = next_call_id(p); + req->call_id = next_call_id(p->conn); req->status = NT_STATUS_OK; req->state = RPC_REQUEST_PENDING; req->payload = data_blob(NULL, 0); @@ -889,20 +867,20 @@ struct rpc_request *dcerpc_request_send(struct dcerpc_pipe *p, req->fault_code = 0; req->async.callback = NULL; - init_dcerpc_hdr(p, &pkt); + init_dcerpc_hdr(p->conn, &pkt); remaining = stub_data->length; /* we can write a full max_recv_frag size, minus the dcerpc request header size */ - chunk_size = p->srv_max_recv_frag - (DCERPC_MAX_SIGN_SIZE+DCERPC_REQUEST_LENGTH); + chunk_size = p->conn->srv_max_recv_frag - (DCERPC_MAX_SIGN_SIZE+DCERPC_REQUEST_LENGTH); pkt.ptype = DCERPC_PKT_REQUEST; pkt.call_id = req->call_id; pkt.auth_length = 0; pkt.pfc_flags = 0; pkt.u.request.alloc_hint = remaining; - pkt.u.request.context_id = 0; + pkt.u.request.context_id = p->context_id; pkt.u.request.opnum = opnum; if (object) { @@ -911,7 +889,7 @@ struct rpc_request *dcerpc_request_send(struct dcerpc_pipe *p, chunk_size -= ndr_size_GUID(object,0); } - DLIST_ADD(p->pending, req); + DLIST_ADD(p->conn->pending, req); /* we send a series of pdus without waiting for a reply */ while (remaining > 0 || first_packet) { @@ -933,17 +911,17 @@ struct rpc_request *dcerpc_request_send(struct dcerpc_pipe *p, (stub_data->length - remaining); pkt.u.request.stub_and_verifier.length = chunk; - req->status = dcerpc_push_request_sign(p, &blob, mem_ctx, &pkt); + req->status = dcerpc_push_request_sign(p->conn, &blob, mem_ctx, &pkt); if (!NT_STATUS_IS_OK(req->status)) { req->state = RPC_REQUEST_DONE; - DLIST_REMOVE(p->pending, req); + DLIST_REMOVE(p->conn->pending, req); return req; } - req->status = p->transport.send_request(p, &blob, last_frag); + req->status = p->conn->transport.send_request(p->conn, &blob, last_frag); if (!NT_STATUS_IS_OK(req->status)) { req->state = RPC_REQUEST_DONE; - DLIST_REMOVE(p->pending, req); + DLIST_REMOVE(p->conn->pending, req); return req; } @@ -961,7 +939,7 @@ struct rpc_request *dcerpc_request_send(struct dcerpc_pipe *p, */ struct event_context *dcerpc_event_context(struct dcerpc_pipe *p) { - return p->transport.event_context(p); + return p->conn->transport.event_context(p->conn); } @@ -1020,7 +998,7 @@ NTSTATUS dcerpc_request(struct dcerpc_pipe *p, for that to the NDR we initially generated. If they don't match then we know we must have a bug in either the pull or push side of our code */ -static NTSTATUS dcerpc_ndr_validate_in(struct dcerpc_pipe *p, +static NTSTATUS dcerpc_ndr_validate_in(struct dcerpc_connection *c, TALLOC_CTX *mem_ctx, DATA_BLOB blob, size_t struct_size, @@ -1038,7 +1016,7 @@ static NTSTATUS dcerpc_ndr_validate_in(struct dcerpc_pipe *p, return NT_STATUS_NO_MEMORY; } - pull = ndr_pull_init_flags(p, &blob, mem_ctx); + pull = ndr_pull_init_flags(c, &blob, mem_ctx); if (!pull) { return NT_STATUS_NO_MEMORY; } @@ -1084,7 +1062,7 @@ static NTSTATUS dcerpc_ndr_validate_in(struct dcerpc_pipe *p, initially generated. If they don't match then we know we must have a bug in either the pull or push side of our code */ -static NTSTATUS dcerpc_ndr_validate_out(struct dcerpc_pipe *p, +static NTSTATUS dcerpc_ndr_validate_out(struct dcerpc_connection *c, TALLOC_CTX *mem_ctx, void *struct_ptr, size_t struct_size, @@ -1117,7 +1095,7 @@ static NTSTATUS dcerpc_ndr_validate_out(struct dcerpc_pipe *p, blob = ndr_push_blob(push); - pull = ndr_pull_init_flags(p, &blob, mem_ctx); + pull = ndr_pull_init_flags(c, &blob, mem_ctx); if (!pull) { return NT_STATUS_NO_MEMORY; } @@ -1182,7 +1160,7 @@ struct rpc_request *dcerpc_ndr_request_send(struct dcerpc_pipe *p, return NULL; } - if (p->flags & DCERPC_PUSH_BIGENDIAN) { + if (p->conn->flags & DCERPC_PUSH_BIGENDIAN) { push->flags |= LIBNDR_FLAG_BIGENDIAN; } @@ -1198,8 +1176,8 @@ struct rpc_request *dcerpc_ndr_request_send(struct dcerpc_pipe *p, /* retrieve the blob */ request = ndr_push_blob(push); - if (p->flags & DCERPC_DEBUG_VALIDATE_IN) { - status = dcerpc_ndr_validate_in(p, mem_ctx, request, call->struct_size, + if (p->conn->flags & DCERPC_DEBUG_VALIDATE_IN) { + status = dcerpc_ndr_validate_in(p->conn, mem_ctx, request, call->struct_size, call->ndr_push, call->ndr_pull); if (!NT_STATUS_IS_OK(status)) { DEBUG(2,("Validation failed in dcerpc_ndr_request_send - %s\n", @@ -1256,7 +1234,7 @@ NTSTATUS dcerpc_ndr_request_recv(struct rpc_request *req) talloc_free(req); /* prepare for ndr_pull_* */ - pull = ndr_pull_init_flags(p, &response, mem_ctx); + pull = ndr_pull_init_flags(p->conn, &response, mem_ctx); if (!pull) { return NT_STATUS_NO_MEMORY; } @@ -1276,8 +1254,8 @@ NTSTATUS dcerpc_ndr_request_recv(struct rpc_request *req) return status; } - if (p->flags & DCERPC_DEBUG_VALIDATE_OUT) { - status = dcerpc_ndr_validate_out(p, mem_ctx, r, call->struct_size, + if (p->conn->flags & DCERPC_DEBUG_VALIDATE_OUT) { + status = dcerpc_ndr_validate_out(p->conn, mem_ctx, r, call->struct_size, call->ndr_push, call->ndr_pull); if (!NT_STATUS_IS_OK(status)) { dcerpc_log_packet(table, opnum, NDR_OUT, @@ -1329,25 +1307,25 @@ NTSTATUS dcerpc_ndr_request(struct dcerpc_pipe *p, */ const char *dcerpc_server_name(struct dcerpc_pipe *p) { - if (!p->transport.peer_name) { + if (!p->conn->transport.peer_name) { return ""; } - return p->transport.peer_name(p); + return p->conn->transport.peer_name(p->conn); } + /* - a useful function to get the auth_level + get the dcerpc auth_level for a open connection */ - -uint32 dcerpc_auth_level(struct dcerpc_pipe *p) +uint32 dcerpc_auth_level(struct dcerpc_connection *c) { uint8_t auth_level; - if (p->flags & DCERPC_SEAL) { + if (c->flags & DCERPC_SEAL) { auth_level = DCERPC_AUTH_LEVEL_PRIVACY; - } else if (p->flags & DCERPC_SIGN) { + } else if (c->flags & DCERPC_SIGN) { auth_level = DCERPC_AUTH_LEVEL_INTEGRITY; - } else if (p->flags & DCERPC_CONNECT) { + } else if (c->flags & DCERPC_CONNECT) { auth_level = DCERPC_AUTH_LEVEL_CONNECT; } else { auth_level = DCERPC_AUTH_LEVEL_NONE; diff --git a/source4/librpc/rpc/dcerpc.h b/source4/librpc/rpc/dcerpc.h index 1b2feeadb2..00f1fb6488 100644 --- a/source4/librpc/rpc/dcerpc.h +++ b/source4/librpc/rpc/dcerpc.h @@ -1,9 +1,10 @@ /* Unix SMB/CIFS implementation. - DCERPC interface structures + + DCERPC client side interface structures Copyright (C) Tim Potter 2003 - Copyright (C) Andrew Tridgell 2003 + Copyright (C) Andrew Tridgell 2003-2005 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -28,17 +29,19 @@ enum dcerpc_transport_t { /* this defines a generic security context for signed/sealed dcerpc pipes. */ -struct dcerpc_pipe; +struct dcerpc_connection; struct dcerpc_security { struct dcerpc_auth *auth_info; struct gensec_security *generic_state; /* get the session key */ - NTSTATUS (*session_key)(struct dcerpc_pipe *, DATA_BLOB *); + NTSTATUS (*session_key)(struct dcerpc_connection *, DATA_BLOB *); }; -struct dcerpc_pipe { - int reference_count; +/* + this holds the information that is not specific to a particular rpc context_id +*/ +struct dcerpc_connection { uint32_t call_id; uint32_t srv_max_xmit_frag; uint32_t srv_max_recv_frag; @@ -46,35 +49,28 @@ struct dcerpc_pipe { struct dcerpc_security security_state; const char *binding_string; - struct dcerpc_syntax_id syntax; - struct dcerpc_syntax_id transfer_syntax; - struct dcerpc_transport { enum dcerpc_transport_t transport; void *private; - NTSTATUS (*shutdown_pipe)(struct dcerpc_pipe *); + NTSTATUS (*shutdown_pipe)(struct dcerpc_connection *); - const char *(*peer_name)(struct dcerpc_pipe *); + const char *(*peer_name)(struct dcerpc_connection *); /* send a request to the server */ - NTSTATUS (*send_request)(struct dcerpc_pipe *, DATA_BLOB *, BOOL trigger_read); + NTSTATUS (*send_request)(struct dcerpc_connection *, DATA_BLOB *, BOOL trigger_read); /* send a read request to the server */ - NTSTATUS (*send_read)(struct dcerpc_pipe *); + NTSTATUS (*send_read)(struct dcerpc_connection *); /* get an event context for the connection */ - struct event_context *(*event_context)(struct dcerpc_pipe *); + struct event_context *(*event_context)(struct dcerpc_connection *); /* a callback to the dcerpc code when a full fragment has been received */ - void (*recv_data)(struct dcerpc_pipe *, DATA_BLOB *, NTSTATUS status); - + void (*recv_data)(struct dcerpc_connection *, DATA_BLOB *, NTSTATUS status); } transport; - /* the last fault code from a DCERPC fault */ - uint32_t last_fault_code; - /* pending requests */ struct rpc_request *pending; @@ -82,6 +78,22 @@ struct dcerpc_pipe { void *full_request_private; }; +/* + this encapsulates a full dcerpc client side pipe +*/ +struct dcerpc_pipe { + uint32_t context_id; + + struct dcerpc_syntax_id syntax; + struct dcerpc_syntax_id transfer_syntax; + + struct dcerpc_connection *conn; + + /* the last fault code from a DCERPC fault */ + uint32_t last_fault_code; +}; + + /* dcerpc pipe flags */ #define DCERPC_DEBUG_PRINT_IN (1<<0) #define DCERPC_DEBUG_PRINT_OUT (1<<1) @@ -141,8 +153,7 @@ struct dcerpc_interface_table { const struct dcerpc_endpoint_list *endpoints; }; -struct dcerpc_interface_list -{ +struct dcerpc_interface_list { struct dcerpc_interface_list *prev, *next; const struct dcerpc_interface_table *table; }; diff --git a/source4/librpc/rpc/dcerpc_auth.c b/source4/librpc/rpc/dcerpc_auth.c index 36e4ba6eea..9d43218e4b 100644 --- a/source4/librpc/rpc/dcerpc_auth.c +++ b/source4/librpc/rpc/dcerpc_auth.c @@ -45,7 +45,7 @@ NTSTATUS dcerpc_bind_auth_none(struct dcerpc_pipe *p, } NTSTATUS dcerpc_bind_auth3(struct dcerpc_pipe *p, uint8_t auth_type, uint8_t auth_level, - const char *uuid, uint_t version) + const char *uuid, uint_t version) { NTSTATUS status; TALLOC_CTX *mem_ctx; @@ -57,33 +57,34 @@ NTSTATUS dcerpc_bind_auth3(struct dcerpc_pipe *p, uint8_t auth_type, uint8_t aut return NT_STATUS_NO_MEMORY; } - if (!p->security_state.generic_state) { - status = gensec_client_start(p, &p->security_state.generic_state); + if (!p->conn->security_state.generic_state) { + status = gensec_client_start(p, &p->conn->security_state.generic_state); if (!NT_STATUS_IS_OK(status)) { return status; } - status = gensec_start_mech_by_authtype(p->security_state.generic_state, auth_type, auth_level); + status = gensec_start_mech_by_authtype(p->conn->security_state.generic_state, + auth_type, auth_level); if (!NT_STATUS_IS_OK(status)) { return status; } } - p->security_state.auth_info = talloc_p(p, struct dcerpc_auth); - if (!p->security_state.auth_info) { + p->conn->security_state.auth_info = talloc(p, struct dcerpc_auth); + if (!p->conn->security_state.auth_info) { status = NT_STATUS_NO_MEMORY; goto done; } - p->security_state.auth_info->auth_type = auth_type; - p->security_state.auth_info->auth_level = auth_level; - p->security_state.auth_info->auth_pad_length = 0; - p->security_state.auth_info->auth_reserved = 0; - p->security_state.auth_info->auth_context_id = random(); - p->security_state.auth_info->credentials = null_data_blob; + p->conn->security_state.auth_info->auth_type = auth_type; + p->conn->security_state.auth_info->auth_level = auth_level; + p->conn->security_state.auth_info->auth_pad_length = 0; + p->conn->security_state.auth_info->auth_reserved = 0; + p->conn->security_state.auth_info->auth_context_id = random(); + p->conn->security_state.auth_info->credentials = null_data_blob; - status = gensec_update(p->security_state.generic_state, mem_ctx, + status = gensec_update(p->conn->security_state.generic_state, mem_ctx, null_data_blob, &credentials); @@ -91,38 +92,40 @@ NTSTATUS dcerpc_bind_auth3(struct dcerpc_pipe *p, uint8_t auth_type, uint8_t aut goto done; } - p->security_state.auth_info->credentials = credentials; + p->conn->security_state.auth_info->credentials = credentials; status = dcerpc_bind_byuuid(p, mem_ctx, uuid, version); if (!NT_STATUS_IS_OK(status)) { goto done; } - status = gensec_update(p->security_state.generic_state, mem_ctx, - p->security_state.auth_info->credentials, + status = gensec_update(p->conn->security_state.generic_state, mem_ctx, + p->conn->security_state.auth_info->credentials, &credentials); if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { goto done; } - p->security_state.auth_info->credentials = credentials; + p->conn->security_state.auth_info->credentials = credentials; - status = dcerpc_auth3(p, mem_ctx); + status = dcerpc_auth3(p->conn, mem_ctx); done: talloc_destroy(mem_ctx); if (!NT_STATUS_IS_OK(status)) { - talloc_free(p->security_state.generic_state); - ZERO_STRUCT(p->security_state); + talloc_free(p->conn->security_state.generic_state); + ZERO_STRUCT(p->conn->security_state); } else { /* Authenticated connections use the generic session key */ - p->security_state.session_key = dcerpc_generic_session_key; + p->conn->security_state.session_key = dcerpc_generic_session_key; } return status; } +#warning "bind_alter not implemented" +#if 0 NTSTATUS dcerpc_bind_alter(struct dcerpc_pipe *p, uint8_t auth_type, uint8_t auth_level, const char *uuid, uint_t version) { @@ -136,13 +139,13 @@ NTSTATUS dcerpc_bind_alter(struct dcerpc_pipe *p, uint8_t auth_type, uint8_t aut return NT_STATUS_NO_MEMORY; } - if (!p->security_state.generic_state) { - status = gensec_client_start(p, &p->security_state.generic_state); + if (!p->conn->security_state.generic_state) { + status = gensec_client_start(p, &p->conn->security_state.generic_state); if (!NT_STATUS_IS_OK(status)) { return status; } - status = gensec_start_mech_by_authtype(p->security_state.generic_state, + status = gensec_start_mech_by_authtype(p->conn->security_state.generic_state, auth_type, auth_level); if (!NT_STATUS_IS_OK(status)) { @@ -150,20 +153,20 @@ NTSTATUS dcerpc_bind_alter(struct dcerpc_pipe *p, uint8_t auth_type, uint8_t aut } } - p->security_state.auth_info = talloc_p(p, struct dcerpc_auth); - if (!p->security_state.auth_info) { + p->conn->security_state.auth_info = talloc_p(p, struct dcerpc_auth); + if (!p->conn->security_state.auth_info) { status = NT_STATUS_NO_MEMORY; goto done; } - p->security_state.auth_info->auth_type = auth_type; - p->security_state.auth_info->auth_level = auth_level; - p->security_state.auth_info->auth_pad_length = 0; - p->security_state.auth_info->auth_reserved = 0; - p->security_state.auth_info->auth_context_id = random(); - p->security_state.auth_info->credentials = null_data_blob; + p->conn->security_state.auth_info->auth_type = auth_type; + p->conn->security_state.auth_info->auth_level = auth_level; + p->conn->security_state.auth_info->auth_pad_length = 0; + p->conn->security_state.auth_info->auth_reserved = 0; + p->conn->security_state.auth_info->auth_context_id = random(); + p->conn->security_state.auth_info->credentials = null_data_blob; - status = gensec_update(p->security_state.generic_state, mem_ctx, + status = gensec_update(p->conn->security_state.generic_state, mem_ctx, null_data_blob, &credentials); @@ -171,7 +174,7 @@ NTSTATUS dcerpc_bind_alter(struct dcerpc_pipe *p, uint8_t auth_type, uint8_t aut goto done; } - p->security_state.auth_info->credentials = credentials; + p->conn->security_state.auth_info->credentials = credentials; status = dcerpc_bind_byuuid(p, mem_ctx, uuid, version); if (!NT_STATUS_IS_OK(status)) { @@ -179,15 +182,15 @@ NTSTATUS dcerpc_bind_alter(struct dcerpc_pipe *p, uint8_t auth_type, uint8_t aut } while(1) { - status = gensec_update(p->security_state.generic_state, mem_ctx, - p->security_state.auth_info->credentials, + status = gensec_update(p->conn->security_state.generic_state, mem_ctx, + p->conn->security_state.auth_info->credentials, &credentials); if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { goto done; } - p->security_state.auth_info->credentials = credentials; + p->conn->security_state.auth_info->credentials = credentials; status = dcerpc_alter(p, mem_ctx); if (!NT_STATUS_IS_OK(status)) { @@ -199,12 +202,13 @@ done: talloc_destroy(mem_ctx); if (!NT_STATUS_IS_OK(status)) { - talloc_free(p->security_state.generic_state); - ZERO_STRUCT(p->security_state); + talloc_free(p->conn->security_state.generic_state); + ZERO_STRUCT(p->conn->security_state); } else { /* Authenticated connections use the generic session key */ - p->security_state.session_key = dcerpc_generic_session_key; + p->conn->security_state.session_key = dcerpc_generic_session_key; } return status; } +#endif diff --git a/source4/librpc/rpc/dcerpc_ntlm.c b/source4/librpc/rpc/dcerpc_ntlm.c index c236b6c516..8a83cea144 100644 --- a/source4/librpc/rpc/dcerpc_ntlm.c +++ b/source4/librpc/rpc/dcerpc_ntlm.c @@ -33,38 +33,39 @@ NTSTATUS dcerpc_bind_auth_ntlm(struct dcerpc_pipe *p, { NTSTATUS status; - if (!(p->flags & (DCERPC_SIGN | DCERPC_SEAL))) { - p->flags |= DCERPC_CONNECT; + if (!(p->conn->flags & (DCERPC_SIGN | DCERPC_SEAL))) { + p->conn->flags |= DCERPC_CONNECT; } - status = gensec_client_start(p, &p->security_state.generic_state); + status = gensec_client_start(p, &p->conn->security_state.generic_state); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Failed to start GENSEC client mode: %s\n", nt_errstr(status))); return status; } - status = gensec_set_domain(p->security_state.generic_state, domain); + status = gensec_set_domain(p->conn->security_state.generic_state, domain); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Failed to start set GENSEC client domain to %s: %s\n", domain, nt_errstr(status))); return status; } - status = gensec_set_username(p->security_state.generic_state, username); + status = gensec_set_username(p->conn->security_state.generic_state, username); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Failed to start set GENSEC client username to %s: %s\n", username, nt_errstr(status))); return status; } - status = gensec_set_password(p->security_state.generic_state, password); + status = gensec_set_password(p->conn->security_state.generic_state, password); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Failed to start set GENSEC client password: %s\n", nt_errstr(status))); return status; } - status = gensec_start_mech_by_authtype(p->security_state.generic_state, DCERPC_AUTH_TYPE_NTLMSSP, dcerpc_auth_level(p)); + status = gensec_start_mech_by_authtype(p->conn->security_state.generic_state, + DCERPC_AUTH_TYPE_NTLMSSP, dcerpc_auth_level(p->conn)); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Failed to start set GENSEC client NTLMSSP mechanism: %s\n", nt_errstr(status))); @@ -72,7 +73,7 @@ NTSTATUS dcerpc_bind_auth_ntlm(struct dcerpc_pipe *p, } status = dcerpc_bind_auth3(p, DCERPC_AUTH_TYPE_NTLMSSP, - dcerpc_auth_level(p), + dcerpc_auth_level(p->conn), uuid, version); if (!NT_STATUS_IS_OK(status)) { diff --git a/source4/librpc/rpc/dcerpc_schannel.c b/source4/librpc/rpc/dcerpc_schannel.c index 8632a3cf16..92e8d0ca38 100644 --- a/source4/librpc/rpc/dcerpc_schannel.c +++ b/source4/librpc/rpc/dcerpc_schannel.c @@ -339,7 +339,7 @@ static NTSTATUS dcerpc_schannel_key(struct dcerpc_pipe *p, const char *workgroup, *workstation; uint32_t negotiate_flags; - if (p->flags & DCERPC_SCHANNEL_128) { + if (p->conn->flags & DCERPC_SCHANNEL_128) { negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; } else { negotiate_flags = NETLOGON_NEG_AUTH2_FLAGS; @@ -424,46 +424,48 @@ NTSTATUS dcerpc_bind_auth_schannel_withkey(struct dcerpc_pipe *p, NTSTATUS status; struct dcerpc_schannel_state *dce_schan_state; - status = gensec_client_start(p, &p->security_state.generic_state); + status = gensec_client_start(p, &p->conn->security_state.generic_state); if (!NT_STATUS_IS_OK(status)) { return status; } - status = gensec_set_username(p->security_state.generic_state, username); + status = gensec_set_username(p->conn->security_state.generic_state, username); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Failed to set schannel username to %s: %s\n", username, nt_errstr(status))); - talloc_free(p->security_state.generic_state); - p->security_state.generic_state = NULL; + talloc_free(p->conn->security_state.generic_state); + p->conn->security_state.generic_state = NULL; return status; } - status = gensec_set_domain(p->security_state.generic_state, domain); + status = gensec_set_domain(p->conn->security_state.generic_state, domain); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Failed to set schannel domain to %s: %s\n", domain, nt_errstr(status))); - talloc_free(p->security_state.generic_state); - p->security_state.generic_state = NULL; + talloc_free(p->conn->security_state.generic_state); + p->conn->security_state.generic_state = NULL; return status; } - status = gensec_start_mech_by_authtype(p->security_state.generic_state, DCERPC_AUTH_TYPE_SCHANNEL, dcerpc_auth_level(p)); + status = gensec_start_mech_by_authtype(p->conn->security_state.generic_state, + DCERPC_AUTH_TYPE_SCHANNEL, + dcerpc_auth_level(p->conn)); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Failed to start SCHANNEL GENSEC backend: %s\n", nt_errstr(status))); - talloc_free(p->security_state.generic_state); - p->security_state.generic_state = NULL; + talloc_free(p->conn->security_state.generic_state); + p->conn->security_state.generic_state = NULL; return status; } - dce_schan_state = p->security_state.generic_state->private_data; + dce_schan_state = p->conn->security_state.generic_state->private_data; dce_schan_state->creds = talloc_reference(dce_schan_state, creds); - status = dcerpc_bind_auth3(p, DCERPC_AUTH_TYPE_SCHANNEL, dcerpc_auth_level(p), - uuid, version); + status = dcerpc_bind_auth3(p, DCERPC_AUTH_TYPE_SCHANNEL, dcerpc_auth_level(p->conn), + uuid, version); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Failed to bind to pipe with SCHANNEL: %s\n", nt_errstr(status))); - talloc_free(p->security_state.generic_state); - p->security_state.generic_state = NULL; + talloc_free(p->conn->security_state.generic_state); + p->conn->security_state.generic_state = NULL; return status; } @@ -484,11 +486,11 @@ NTSTATUS dcerpc_bind_auth_schannel(struct dcerpc_pipe *p, return NT_STATUS_NO_MEMORY; } - if (p->flags & DCERPC_SCHANNEL_BDC) { + if (p->conn->flags & DCERPC_SCHANNEL_BDC) { chan_type = SEC_CHAN_BDC; - } else if (p->flags & DCERPC_SCHANNEL_WORKSTATION) { + } else if (p->conn->flags & DCERPC_SCHANNEL_WORKSTATION) { chan_type = SEC_CHAN_WKSTA; - } else if (p->flags & DCERPC_SCHANNEL_DOMAIN) { + } else if (p->conn->flags & DCERPC_SCHANNEL_DOMAIN) { chan_type = SEC_CHAN_DOMAIN; } diff --git a/source4/librpc/rpc/dcerpc_smb.c b/source4/librpc/rpc/dcerpc_smb.c index ab8a60b060..837561981f 100644 --- a/source4/librpc/rpc/dcerpc_smb.c +++ b/source4/librpc/rpc/dcerpc_smb.c @@ -35,9 +35,9 @@ struct smb_private { /* tell the dcerpc layer that the transport is dead */ -static void pipe_dead(struct dcerpc_pipe *p, NTSTATUS status) +static void pipe_dead(struct dcerpc_connection *c, NTSTATUS status) { - p->transport.recv_data(p, NULL, status); + c->transport.recv_data(c, NULL, status); } @@ -45,7 +45,7 @@ static void pipe_dead(struct dcerpc_pipe *p, NTSTATUS status) this holds the state of an in-flight call */ struct smb_read_state { - struct dcerpc_pipe *p; + struct dcerpc_connection *c; struct smbcli_request *req; size_t received; DATA_BLOB data; @@ -64,12 +64,12 @@ static void smb_read_callback(struct smbcli_request *req) NTSTATUS status; state = req->async.private; - smb = state->p->transport.private; + smb = state->c->transport.private; io = state->io; status = smb_raw_read_recv(state->req, io); if (NT_STATUS_IS_ERR(status)) { - pipe_dead(state->p, status); + pipe_dead(state->c, status); talloc_free(state); return; } @@ -79,7 +79,7 @@ static void smb_read_callback(struct smbcli_request *req) if (state->received < 16) { DEBUG(0,("dcerpc_smb: short packet (length %d) in read callback!\n", state->received)); - pipe_dead(state->p, NT_STATUS_INFO_LENGTH_MISMATCH); + pipe_dead(state->c, NT_STATUS_INFO_LENGTH_MISMATCH); talloc_free(state); return; } @@ -88,7 +88,7 @@ static void smb_read_callback(struct smbcli_request *req) if (frag_length <= state->received) { state->data.length = state->received; - state->p->transport.recv_data(state->p, &state->data, NT_STATUS_OK); + state->c->transport.recv_data(state->c, &state->data, NT_STATUS_OK); talloc_free(state); return; } @@ -96,14 +96,14 @@ static void smb_read_callback(struct smbcli_request *req) /* initiate another read request, as we only got part of a fragment */ state->data.data = talloc_realloc(state, state->data.data, uint8_t, frag_length); - io->readx.in.mincnt = MIN(state->p->srv_max_xmit_frag, + io->readx.in.mincnt = MIN(state->c->srv_max_xmit_frag, frag_length - state->received); io->readx.in.maxcnt = io->readx.in.mincnt; io->readx.out.data = state->data.data + state->received; state->req = smb_raw_read_send(smb->tree, io); if (state->req == NULL) { - pipe_dead(state->p, NT_STATUS_NO_MEMORY); + pipe_dead(state->c, NT_STATUS_NO_MEMORY); talloc_free(state); return; } @@ -116,9 +116,9 @@ static void smb_read_callback(struct smbcli_request *req) trigger a read request from the server, possibly with some initial data in the read buffer */ -static NTSTATUS send_read_request_continue(struct dcerpc_pipe *p, DATA_BLOB *blob) +static NTSTATUS send_read_request_continue(struct dcerpc_connection *c, DATA_BLOB *blob) { - struct smb_private *smb = p->transport.private; + struct smb_private *smb = c->transport.private; union smb_read *io; struct smb_read_state *state; struct smbcli_request *req; @@ -128,7 +128,7 @@ static NTSTATUS send_read_request_continue(struct dcerpc_pipe *p, DATA_BLOB *blo return NT_STATUS_NO_MEMORY; } - state->p = p; + state->c = c; if (blob == NULL) { state->received = 0; state->data = data_blob_talloc(state, NULL, 0x2000); @@ -171,16 +171,16 @@ static NTSTATUS send_read_request_continue(struct dcerpc_pipe *p, DATA_BLOB *blo /* trigger a read request from the server */ -static NTSTATUS send_read_request(struct dcerpc_pipe *p) +static NTSTATUS send_read_request(struct dcerpc_connection *c) { - return send_read_request_continue(p, NULL); + return send_read_request_continue(c, NULL); } /* this holds the state of an in-flight trans call */ struct smb_trans_state { - struct dcerpc_pipe *p; + struct dcerpc_connection *c; struct smbcli_request *req; struct smb_trans2 *trans; }; @@ -191,33 +191,33 @@ struct smb_trans_state { static void smb_trans_callback(struct smbcli_request *req) { struct smb_trans_state *state = req->async.private; - struct dcerpc_pipe *p = state->p; + struct dcerpc_connection *c = state->c; NTSTATUS status; status = smb_raw_trans_recv(req, state, state->trans); if (NT_STATUS_IS_ERR(status)) { - pipe_dead(p, status); + pipe_dead(c, status); return; } if (!NT_STATUS_EQUAL(status, STATUS_BUFFER_OVERFLOW)) { - p->transport.recv_data(p, &state->trans->out.data, NT_STATUS_OK); + c->transport.recv_data(c, &state->trans->out.data, NT_STATUS_OK); talloc_free(state); return; } /* there is more to receive - setup a readx */ - send_read_request_continue(p, &state->trans->out.data); + send_read_request_continue(c, &state->trans->out.data); talloc_free(state); } /* send a SMBtrans style request */ -static NTSTATUS smb_send_trans_request(struct dcerpc_pipe *p, DATA_BLOB *blob) +static NTSTATUS smb_send_trans_request(struct dcerpc_connection *c, DATA_BLOB *blob) { - struct smb_private *smb = p->transport.private; + struct smb_private *smb = c->transport.private; struct smb_trans2 *trans; uint16 setup[2]; struct smb_trans_state *state; @@ -227,7 +227,7 @@ static NTSTATUS smb_send_trans_request(struct dcerpc_pipe *p, DATA_BLOB *blob) return NT_STATUS_NO_MEMORY; } - state->p = p; + state->c = c; state->trans = talloc_p(state, struct smb_trans2); trans = state->trans; @@ -263,11 +263,11 @@ static NTSTATUS smb_send_trans_request(struct dcerpc_pipe *p, DATA_BLOB *blob) */ static void smb_write_callback(struct smbcli_request *req) { - struct dcerpc_pipe *p = req->async.private; + struct dcerpc_connection *c = req->async.private; if (!NT_STATUS_IS_OK(req->status)) { DEBUG(0,("dcerpc_smb: write callback error\n")); - pipe_dead(p, req->status); + pipe_dead(c, req->status); } smbcli_request_destroy(req); @@ -276,14 +276,14 @@ static void smb_write_callback(struct smbcli_request *req) /* send a packet to the server */ -static NTSTATUS smb_send_request(struct dcerpc_pipe *p, DATA_BLOB *blob, BOOL trigger_read) +static NTSTATUS smb_send_request(struct dcerpc_connection *c, DATA_BLOB *blob, BOOL trigger_read) { - struct smb_private *smb = p->transport.private; + struct smb_private *smb = c->transport.private; union smb_write io; struct smbcli_request *req; if (trigger_read) { - return smb_send_trans_request(p, blob); + return smb_send_trans_request(c, blob); } io.generic.level = RAW_WRITE_WRITEX; @@ -300,10 +300,10 @@ static NTSTATUS smb_send_request(struct dcerpc_pipe *p, DATA_BLOB *blob, BOOL tr } req->async.fn = smb_write_callback; - req->async.private = p; + req->async.private = c; if (trigger_read) { - send_read_request(p); + send_read_request(c); } return NT_STATUS_OK; @@ -313,9 +313,9 @@ static NTSTATUS smb_send_request(struct dcerpc_pipe *p, DATA_BLOB *blob, BOOL tr return the event context for the pipe, so the caller can wait for events asynchronously */ -static struct event_context *smb_event_context(struct dcerpc_pipe *p) +static struct event_context *smb_event_context(struct dcerpc_connection *c) { - struct smb_private *smb = p->transport.private; + struct smb_private *smb = c->transport.private; return smb->tree->session->transport->event.ctx; } @@ -324,18 +324,18 @@ static struct event_context *smb_event_context(struct dcerpc_pipe *p) /* shutdown SMB pipe connection */ -static NTSTATUS smb_shutdown_pipe(struct dcerpc_pipe *p) +static NTSTATUS smb_shutdown_pipe(struct dcerpc_connection *c) { - struct smb_private *smb = p->transport.private; - union smb_close c; + struct smb_private *smb = c->transport.private; + union smb_close io; /* maybe we're still starting up */ if (!smb) return NT_STATUS_OK; - c.close.level = RAW_CLOSE_CLOSE; - c.close.in.fnum = smb->fnum; - c.close.in.write_time = 0; - smb_raw_close(smb->tree, &c); + io.close.level = RAW_CLOSE_CLOSE; + io.close.in.fnum = smb->fnum; + io.close.in.write_time = 0; + smb_raw_close(smb->tree, &io); talloc_free(smb); @@ -345,18 +345,18 @@ static NTSTATUS smb_shutdown_pipe(struct dcerpc_pipe *p) /* return SMB server name */ -static const char *smb_peer_name(struct dcerpc_pipe *p) +static const char *smb_peer_name(struct dcerpc_connection *c) { - struct smb_private *smb = p->transport.private; + struct smb_private *smb = c->transport.private; return smb->tree->session->transport->called.name; } /* fetch the user session key */ -static NTSTATUS smb_session_key(struct dcerpc_pipe *p, DATA_BLOB *session_key) +static NTSTATUS smb_session_key(struct dcerpc_connection *c, DATA_BLOB *session_key) { - struct smb_private *smb = p->transport.private; + struct smb_private *smb = c->transport.private; if (smb->tree->session->user_session_key.data) { *session_key = smb->tree->session->user_session_key; @@ -368,7 +368,7 @@ static NTSTATUS smb_session_key(struct dcerpc_pipe *p, DATA_BLOB *session_key) /* open a rpc connection to a named pipe */ -NTSTATUS dcerpc_pipe_open_smb(struct dcerpc_pipe **p, +NTSTATUS dcerpc_pipe_open_smb(struct dcerpc_connection *c, struct smbcli_tree *tree, const char *pipe_name) { @@ -402,36 +402,31 @@ NTSTATUS dcerpc_pipe_open_smb(struct dcerpc_pipe **p, return status; } - if (!(*p = dcerpc_pipe_init())) { - return NT_STATUS_NO_MEMORY; - } - /* fill in the transport methods */ - (*p)->transport.transport = NCACN_NP; - (*p)->transport.private = NULL; - (*p)->transport.shutdown_pipe = smb_shutdown_pipe; - (*p)->transport.peer_name = smb_peer_name; - - (*p)->transport.send_request = smb_send_request; - (*p)->transport.send_read = send_read_request; - (*p)->transport.event_context = smb_event_context; - (*p)->transport.recv_data = NULL; + c->transport.transport = NCACN_NP; + c->transport.private = NULL; + c->transport.shutdown_pipe = smb_shutdown_pipe; + c->transport.peer_name = smb_peer_name; + + c->transport.send_request = smb_send_request; + c->transport.send_read = send_read_request; + c->transport.event_context = smb_event_context; + c->transport.recv_data = NULL; /* Over-ride the default session key with the SMB session key */ - (*p)->security_state.session_key = smb_session_key; + c->security_state.session_key = smb_session_key; - smb = talloc_p((*p), struct smb_private); - if (!smb) { - dcerpc_pipe_close(*p); + smb = talloc_p(c, struct smb_private); + if (smb == NULL) { return NT_STATUS_NO_MEMORY; } smb->fnum = io.ntcreatex.out.fnum; smb->tree = tree; - (*p)->transport.private = smb; + c->transport.private = smb; return NT_STATUS_OK; } @@ -439,11 +434,11 @@ NTSTATUS dcerpc_pipe_open_smb(struct dcerpc_pipe **p, /* return the SMB tree used for a dcerpc over SMB pipe */ -struct smbcli_tree *dcerpc_smb_tree(struct dcerpc_pipe *p) +struct smbcli_tree *dcerpc_smb_tree(struct dcerpc_connection *c) { - struct smb_private *smb = p->transport.private; + struct smb_private *smb = c->transport.private; - if (p->transport.transport != NCACN_NP) { + if (c->transport.transport != NCACN_NP) { return NULL; } diff --git a/source4/librpc/rpc/dcerpc_sock.c b/source4/librpc/rpc/dcerpc_sock.c index 762a22ad3e..b48fedb0d8 100644 --- a/source4/librpc/rpc/dcerpc_sock.c +++ b/source4/librpc/rpc/dcerpc_sock.c @@ -54,7 +54,7 @@ struct sock_private { /* mark the socket dead */ -static void sock_dead(struct dcerpc_pipe *p, NTSTATUS status) +static void sock_dead(struct dcerpc_connection *p, NTSTATUS status) { struct sock_private *sock = p->transport.private; @@ -80,7 +80,7 @@ static void sock_dead(struct dcerpc_pipe *p, NTSTATUS status) /* process send requests */ -static void sock_process_send(struct dcerpc_pipe *p) +static void sock_process_send(struct dcerpc_connection *p) { struct sock_private *sock = p->transport.private; @@ -117,7 +117,7 @@ static void sock_process_send(struct dcerpc_pipe *p) /* process recv requests */ -static void sock_process_recv(struct dcerpc_pipe *p) +static void sock_process_recv(struct dcerpc_connection *p) { struct sock_private *sock = p->transport.private; NTSTATUS status; @@ -194,7 +194,7 @@ static void sock_process_recv(struct dcerpc_pipe *p) static void sock_io_handler(struct event_context *ev, struct fd_event *fde, struct timeval t, uint16_t flags) { - struct dcerpc_pipe *p = fde->private; + struct dcerpc_connection *p = fde->private; struct sock_private *sock = p->transport.private; if (flags & EVENT_FD_WRITE) { @@ -213,7 +213,7 @@ static void sock_io_handler(struct event_context *ev, struct fd_event *fde, /* initiate a read request */ -static NTSTATUS sock_send_read(struct dcerpc_pipe *p) +static NTSTATUS sock_send_read(struct dcerpc_connection *p) { struct sock_private *sock = p->transport.private; @@ -227,7 +227,7 @@ static NTSTATUS sock_send_read(struct dcerpc_pipe *p) /* send an initial pdu in a multi-pdu sequence */ -static NTSTATUS sock_send_request(struct dcerpc_pipe *p, DATA_BLOB *data, BOOL trigger_read) +static NTSTATUS sock_send_request(struct dcerpc_connection *p, DATA_BLOB *data, BOOL trigger_read) { struct sock_private *sock = p->transport.private; struct sock_blob *blob; @@ -261,7 +261,7 @@ static NTSTATUS sock_send_request(struct dcerpc_pipe *p, DATA_BLOB *data, BOOL t /* return the event context so the caller can process asynchronously */ -static struct event_context *sock_event_context(struct dcerpc_pipe *p) +static struct event_context *sock_event_context(struct dcerpc_connection *p) { struct sock_private *sock = p->transport.private; @@ -271,7 +271,7 @@ static struct event_context *sock_event_context(struct dcerpc_pipe *p) /* shutdown sock pipe connection */ -static NTSTATUS sock_shutdown_pipe(struct dcerpc_pipe *p) +static NTSTATUS sock_shutdown_pipe(struct dcerpc_connection *p) { sock_dead(p, NT_STATUS_OK); @@ -281,7 +281,7 @@ static NTSTATUS sock_shutdown_pipe(struct dcerpc_pipe *p) /* return sock server name */ -static const char *sock_peer_name(struct dcerpc_pipe *p) +static const char *sock_peer_name(struct dcerpc_connection *p) { struct sock_private *sock = p->transport.private; return sock->server_name; @@ -290,7 +290,7 @@ static const char *sock_peer_name(struct dcerpc_pipe *p) /* open a rpc connection using the generic socket library */ -static NTSTATUS dcerpc_pipe_open_socket(struct dcerpc_pipe **p, +static NTSTATUS dcerpc_pipe_open_socket(struct dcerpc_connection *c, const char *server, uint32_t port, const char *type, @@ -301,45 +301,40 @@ static NTSTATUS dcerpc_pipe_open_socket(struct dcerpc_pipe **p, struct fd_event fde; NTSTATUS status; - if (!(*p = dcerpc_pipe_init())) { - return NT_STATUS_NO_MEMORY; - } - - sock = talloc_p((*p), struct sock_private); + sock = talloc_p(c, struct sock_private); if (!sock) { - talloc_free(*p); return NT_STATUS_NO_MEMORY; } status = socket_create(type, SOCKET_TYPE_STREAM, &socket_ctx, 0); if (!NT_STATUS_IS_OK(status)) { - talloc_free(*p); + talloc_free(sock); return status; } talloc_steal(sock, socket_ctx); status = socket_connect(socket_ctx, NULL, 0, server, port, 0); if (!NT_STATUS_IS_OK(status)) { - talloc_free(*p); + talloc_free(sock); return status; } /* fill in the transport methods */ - (*p)->transport.transport = transport; - (*p)->transport.private = NULL; + c->transport.transport = transport; + c->transport.private = NULL; - (*p)->transport.send_request = sock_send_request; - (*p)->transport.send_read = sock_send_read; - (*p)->transport.event_context = sock_event_context; - (*p)->transport.recv_data = NULL; + c->transport.send_request = sock_send_request; + c->transport.send_read = sock_send_read; + c->transport.event_context = sock_event_context; + c->transport.recv_data = NULL; - (*p)->transport.shutdown_pipe = sock_shutdown_pipe; - (*p)->transport.peer_name = sock_peer_name; + c->transport.shutdown_pipe = sock_shutdown_pipe; + c->transport.peer_name = sock_peer_name; sock->sock = socket_ctx; - sock->server_name = talloc_strdup((*p), server); + sock->server_name = talloc_strdup(sock, server); sock->event_ctx = event_context_init(sock); sock->pending_send = NULL; sock->recv.received = 0; @@ -349,11 +344,11 @@ static NTSTATUS dcerpc_pipe_open_socket(struct dcerpc_pipe **p, fde.fd = socket_get_fd(sock->sock); fde.flags = 0; fde.handler = sock_io_handler; - fde.private = *p; + fde.private = c; sock->fde = event_add_fd(sock->event_ctx, &fde); - (*p)->transport.private = sock; + c->transport.private = sock; /* ensure we don't get SIGPIPE */ BlockSignals(True,SIGPIPE); @@ -364,31 +359,31 @@ static NTSTATUS dcerpc_pipe_open_socket(struct dcerpc_pipe **p, /* open a rpc connection using tcp */ -NTSTATUS dcerpc_pipe_open_tcp(struct dcerpc_pipe **p, const char *server, uint32_t port) +NTSTATUS dcerpc_pipe_open_tcp(struct dcerpc_connection *c, const char *server, uint32_t port) { NTSTATUS status; /* Try IPv6 first */ - status = dcerpc_pipe_open_socket(p, server, port, "ipv6", NCACN_IP_TCP); + status = dcerpc_pipe_open_socket(c, server, port, "ipv6", NCACN_IP_TCP); if (NT_STATUS_IS_OK(status)) { return status; } - return dcerpc_pipe_open_socket(p, server, port, "ipv4", NCACN_IP_TCP); + return dcerpc_pipe_open_socket(c, server, port, "ipv4", NCACN_IP_TCP); } /* open a rpc connection to a unix socket */ -NTSTATUS dcerpc_pipe_open_unix_stream(struct dcerpc_pipe **p, const char *path) +NTSTATUS dcerpc_pipe_open_unix_stream(struct dcerpc_connection *c, const char *path) { - return dcerpc_pipe_open_socket(p, path, 0, "unix", NCACN_UNIX_STREAM); + return dcerpc_pipe_open_socket(c, path, 0, "unix", NCACN_UNIX_STREAM); } /* open a rpc connection to a named pipe */ -NTSTATUS dcerpc_pipe_open_pipe(struct dcerpc_pipe **p, const char *identifier) +NTSTATUS dcerpc_pipe_open_pipe(struct dcerpc_connection *c, const char *identifier) { NTSTATUS status; char *canon, *full_path; @@ -398,7 +393,7 @@ NTSTATUS dcerpc_pipe_open_pipe(struct dcerpc_pipe **p, const char *identifier) string_replace(canon, '/', '\\'); full_path = talloc_asprintf(canon, "%s/%s", lp_ncalrpc_dir(), canon); - status = dcerpc_pipe_open_socket(p, full_path, 0, "unix", NCALRPC); + status = dcerpc_pipe_open_socket(c, full_path, 0, "unix", NCALRPC); talloc_free(canon); return status; diff --git a/source4/librpc/rpc/dcerpc_spnego.c b/source4/librpc/rpc/dcerpc_spnego.c index d15224b981..cab8865d6b 100644 --- a/source4/librpc/rpc/dcerpc_spnego.c +++ b/source4/librpc/rpc/dcerpc_spnego.c @@ -3,7 +3,9 @@ dcerpc authentication operations - Copyright (C) Andrew Tridgell 2003 + Copyright (C) Stefan Metzmacher 2004 + Copyright (C) Andrew Tridgell 2003-2005 + Copyright (C) Andrew Bartlett 2004 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,6 +24,8 @@ #include "includes.h" +#warning "this needs dcerpc_alter" +#if 0 /* do spnego style authentication on a gensec pipe */ @@ -33,49 +37,53 @@ NTSTATUS dcerpc_bind_auth_spnego(struct dcerpc_pipe *p, { NTSTATUS status; - status = gensec_client_start(p, &p->security_state.generic_state); + status = gensec_client_start(p, &p->conn->security_state.generic_state); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Failed to start GENSEC client mode: %s\n", nt_errstr(status))); return status; } - status = gensec_set_domain(p->security_state.generic_state, domain); + status = gensec_set_domain(p->conn->security_state.generic_state, domain); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Failed to start set GENSEC client domain to %s: %s\n", domain, nt_errstr(status))); return status; } - status = gensec_set_username(p->security_state.generic_state, username); + status = gensec_set_username(p->conn->security_state.generic_state, username); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Failed to start set GENSEC client username to %s: %s\n", username, nt_errstr(status))); return status; } - status = gensec_set_password(p->security_state.generic_state, password); + status = gensec_set_password(p->conn->security_state.generic_state, password); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Failed to start set GENSEC client password: %s\n", nt_errstr(status))); return status; } - status = gensec_set_target_hostname(p->security_state.generic_state, p->transport.peer_name(p)); + status = gensec_set_target_hostname(p->conn->security_state.generic_state, + p->conn->transport.peer_name(p->conn)); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Failed to start set GENSEC target hostname: %s\n", nt_errstr(status))); return status; } - status = gensec_start_mech_by_authtype(p->security_state.generic_state, DCERPC_AUTH_TYPE_SPNEGO, dcerpc_auth_level(p)); + status = gensec_start_mech_by_authtype(p->conn->security_state.generic_state, + DCERPC_AUTH_TYPE_SPNEGO, + dcerpc_auth_level(p->conn)); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Failed to start set GENSEC client SPNEGO mechanism: %s\n", nt_errstr(status))); return status; } - status = dcerpc_bind_alter(p, DCERPC_AUTH_TYPE_SPNEGO, dcerpc_auth_level(p), - uuid, version); + status = dcerpc_bind_alter(p, DCERPC_AUTH_TYPE_SPNEGO, + dcerpc_auth_level(p->conn), + uuid, version); if (!NT_STATUS_IS_OK(status)) { DEBUG(2, ("Failed to bind to pipe with SPNEGO: %s\n", nt_errstr(status))); @@ -84,3 +92,4 @@ NTSTATUS dcerpc_bind_auth_spnego(struct dcerpc_pipe *p, return status; } +#endif diff --git a/source4/librpc/rpc/dcerpc_util.c b/source4/librpc/rpc/dcerpc_util.c index 4adeee7a37..67b0c530bf 100644 --- a/source4/librpc/rpc/dcerpc_util.c +++ b/source4/librpc/rpc/dcerpc_util.c @@ -30,8 +30,8 @@ */ const char *idl_pipe_name(const char *uuid, uint32_t if_version) { - struct dcerpc_interface_list *l; - for (l=dcerpc_pipes;l;l=l->next) { + const struct dcerpc_interface_list *l; + for (l=librpc_dcerpc_pipes();l;l=l->next) { if (strcasecmp(l->table->uuid, uuid) == 0 && l->table->if_version == if_version) { return l->table->name; @@ -45,8 +45,8 @@ const char *idl_pipe_name(const char *uuid, uint32_t if_version) */ int idl_num_calls(const char *uuid, uint32_t if_version) { - struct dcerpc_interface_list *l; - for (l=dcerpc_pipes;l;l=l->next){ + const struct dcerpc_interface_list *l; + for (l=librpc_dcerpc_pipes();l;l=l->next){ if (strcasecmp(l->table->uuid, uuid) == 0 && l->table->if_version == if_version) { return l->table->num_calls; @@ -61,8 +61,8 @@ int idl_num_calls(const char *uuid, uint32_t if_version) */ const struct dcerpc_interface_table *idl_iface_by_name(const char *name) { - struct dcerpc_interface_list *l; - for (l=dcerpc_pipes;l;l=l->next) { + const struct dcerpc_interface_list *l; + for (l=librpc_dcerpc_pipes();l;l=l->next) { if (strcasecmp(l->table->name, name) == 0) { return l->table; } @@ -75,8 +75,8 @@ const struct dcerpc_interface_table *idl_iface_by_name(const char *name) */ const struct dcerpc_interface_table *idl_iface_by_uuid(const char *uuid) { - struct dcerpc_interface_list *l; - for (l=dcerpc_pipes;l;l=l->next) { + const struct dcerpc_interface_list *l; + for (l=librpc_dcerpc_pipes();l;l=l->next) { if (strcasecmp(l->table->uuid, uuid) == 0) { return l->table; } @@ -774,7 +774,7 @@ NTSTATUS dcerpc_epm_map_binding(TALLOC_CTX *mem_ctx, struct dcerpc_binding *bind /* open a rpc connection to a rpc pipe on SMB using the binding structure to determine the endpoint and options */ -static NTSTATUS dcerpc_pipe_connect_ncacn_np(struct dcerpc_pipe **p, +static NTSTATUS dcerpc_pipe_connect_ncacn_np(struct dcerpc_pipe **pp, struct dcerpc_binding *binding, const char *pipe_uuid, uint32_t pipe_version, @@ -782,19 +782,28 @@ static NTSTATUS dcerpc_pipe_connect_ncacn_np(struct dcerpc_pipe **p, const char *username, const char *password) { + struct dcerpc_pipe *p; NTSTATUS status; BOOL retry; struct smbcli_state *cli; const char *pipe_name = NULL; - TALLOC_CTX *mem_ctx = talloc_init("dcerpc_pipe_connect_ncacn_np"); + TALLOC_CTX *tmp_ctx; + + *pp = NULL; + + p = dcerpc_pipe_init(NULL); + if (p == NULL) { + return NT_STATUS_NO_MEMORY; + } + tmp_ctx = talloc_new(p); /* Look up identifier using the epmapper */ if (!binding->endpoint) { - status = dcerpc_epm_map_binding(mem_ctx, binding, pipe_uuid, pipe_version); + status = dcerpc_epm_map_binding(tmp_ctx, binding, pipe_uuid, pipe_version); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("Failed to map DCERPC/TCP NCACN_NP pipe for '%s' - %s\n", pipe_uuid, nt_errstr(status))); - talloc_destroy(mem_ctx); + talloc_free(p); return status; } DEBUG(1,("Mapped to DCERPC/NP pipe %s\n", binding->endpoint)); @@ -803,188 +812,199 @@ static NTSTATUS dcerpc_pipe_connect_ncacn_np(struct dcerpc_pipe **p, pipe_name = binding->endpoint; if (!strncasecmp(pipe_name, "/pipe/", 6) || - !strncasecmp(pipe_name, "\\pipe\\", 6)) { - pipe_name+=6; + !strncasecmp(pipe_name, "\\pipe\\", 6)) { + pipe_name += 6; } if (pipe_name[0] != '\\') { - pipe_name = talloc_asprintf(mem_ctx, "\\%s", pipe_name); + pipe_name = talloc_asprintf(tmp_ctx, "\\%s", pipe_name); } if (!username || !username[0] || (binding->flags & DCERPC_SCHANNEL_ANY)) { - status = smbcli_full_connection(NULL, &cli, lp_netbios_name(), - binding->host, NULL, - "ipc$", "?????", - "", "", NULL, 0, &retry); + status = smbcli_full_connection(p->conn, &cli, lp_netbios_name(), + binding->host, NULL, + "ipc$", "?????", + "", "", NULL, 0, &retry); } else { - status = smbcli_full_connection(NULL, &cli, lp_netbios_name(), - binding->host, NULL, - "ipc$", "?????", - username, domain, - password, 0, &retry); + status = smbcli_full_connection(p->conn, &cli, lp_netbios_name(), + binding->host, NULL, + "ipc$", "?????", + username, domain, + password, 0, &retry); } if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("Failed to connect to %s - %s\n", binding->host, nt_errstr(status))); - talloc_destroy(mem_ctx); + talloc_free(p); return status; } - status = dcerpc_pipe_open_smb(p, cli->tree, pipe_name); + status = dcerpc_pipe_open_smb(p->conn, cli->tree, pipe_name); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("Failed to open pipe %s - %s\n", pipe_name, nt_errstr(status))); - smbcli_tdis(cli); - smbcli_shutdown(cli); - talloc_destroy(mem_ctx); + talloc_free(p); return status; } - /* this ensures that the reference count is decremented so - a pipe close will really close the link */ - talloc_steal(*p, cli); - - (*p)->flags = binding->flags; + p->conn->flags = binding->flags; /* remember the binding string for possible secondary connections */ - (*p)->binding_string = dcerpc_binding_string((*p), binding); - - talloc_destroy(mem_ctx); + p->conn->binding_string = dcerpc_binding_string(p, binding); if (username && username[0] && (binding->flags & DCERPC_SCHANNEL_ANY)) { - status = dcerpc_bind_auth_schannel(*p, pipe_uuid, pipe_version, + status = dcerpc_bind_auth_schannel(p, pipe_uuid, pipe_version, domain, username, password); } else if (username && username[0] && (binding->flags & (DCERPC_CONNECT|DCERPC_SIGN|DCERPC_SEAL))) { - status = dcerpc_bind_auth_ntlm(*p, pipe_uuid, pipe_version, domain, username, password); + status = dcerpc_bind_auth_ntlm(p, pipe_uuid, pipe_version, domain, username, password); } else { - status = dcerpc_bind_auth_none(*p, pipe_uuid, pipe_version); + status = dcerpc_bind_auth_none(p, pipe_uuid, pipe_version); } if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("Failed to bind to uuid %s - %s\n", pipe_uuid, nt_errstr(status))); - dcerpc_pipe_close(*p); - *p = NULL; + talloc_free(p); return status; } + (*pp) = p; + talloc_free(tmp_ctx); + return NT_STATUS_OK; } /* open a rpc connection to a rpc pipe on SMP using the binding structure to determine the endpoint and options */ -static NTSTATUS dcerpc_pipe_connect_ncalrpc(struct dcerpc_pipe **p, - struct dcerpc_binding *binding, - const char *pipe_uuid, - uint32_t pipe_version, - const char *domain, - const char *username, - const char *password) +static NTSTATUS dcerpc_pipe_connect_ncalrpc(struct dcerpc_pipe **pp, + struct dcerpc_binding *binding, + const char *pipe_uuid, + uint32_t pipe_version, + const char *domain, + const char *username, + const char *password) { NTSTATUS status; - TALLOC_CTX *mem_ctx = talloc_init("dcerpc_pipe_connect_ncalrpc"); + struct dcerpc_pipe *p; + TALLOC_CTX *tmp_ctx; + + (*pp) = NULL; + + p = dcerpc_pipe_init(NULL); + if (p == NULL) { + return NT_STATUS_NO_MEMORY; + } + tmp_ctx = talloc_new(p); /* Look up identifier using the epmapper */ if (!binding->endpoint) { - status = dcerpc_epm_map_binding(mem_ctx, binding, pipe_uuid, pipe_version); + status = dcerpc_epm_map_binding(tmp_ctx, binding, pipe_uuid, pipe_version); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("Failed to map DCERPC/TCP NCALRPC identifier for '%s' - %s\n", pipe_uuid, nt_errstr(status))); - talloc_destroy(mem_ctx); + talloc_free(p); return status; } DEBUG(1,("Mapped to DCERPC/LRPC identifier %s\n", binding->endpoint)); } - status = dcerpc_pipe_open_pipe(p, binding->endpoint); - + status = dcerpc_pipe_open_pipe(p->conn, binding->endpoint); if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("Failed to open ncalrpc pipe '%s' - %s\n", binding->endpoint, nt_errstr(status))); - talloc_destroy(mem_ctx); + DEBUG(0,("Failed to open ncalrpc pipe '%s' - %s\n", + binding->endpoint, nt_errstr(status))); + talloc_free(p); return status; - } + } - (*p)->flags = binding->flags; + p->conn->flags = binding->flags; /* remember the binding string for possible secondary connections */ - (*p)->binding_string = dcerpc_binding_string((*p), binding); + p->conn->binding_string = dcerpc_binding_string(p, binding); if (username && username[0] && (binding->flags & DCERPC_SCHANNEL_ANY)) { - status = dcerpc_bind_auth_schannel(*p, pipe_uuid, pipe_version, + status = dcerpc_bind_auth_schannel(p, pipe_uuid, pipe_version, domain, username, password); } else if (username && username[0]) { - status = dcerpc_bind_auth_ntlm(*p, pipe_uuid, pipe_version, domain, username, password); + status = dcerpc_bind_auth_ntlm(p, pipe_uuid, pipe_version, domain, username, password); } else { - status = dcerpc_bind_auth_none(*p, pipe_uuid, pipe_version); + status = dcerpc_bind_auth_none(p, pipe_uuid, pipe_version); } if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("Failed to bind to uuid %s - %s\n", - pipe_uuid, nt_errstr(status))); - dcerpc_pipe_close(*p); - *p = NULL; - talloc_destroy(mem_ctx); + DEBUG(0,("Failed to bind to uuid %s - %s\n", pipe_uuid, nt_errstr(status))); + talloc_free(p); return status; } - - talloc_destroy(mem_ctx); - return status; + + (*pp) = p; + talloc_free(tmp_ctx); + + return status; } /* open a rpc connection to a rpc pipe on SMP using the binding structure to determine the endpoint and options */ -static NTSTATUS dcerpc_pipe_connect_ncacn_unix_stream(struct dcerpc_pipe **p, - struct dcerpc_binding *binding, - const char *pipe_uuid, - uint32_t pipe_version, - const char *domain, - const char *username, - const char *password) +static NTSTATUS dcerpc_pipe_connect_ncacn_unix_stream(struct dcerpc_pipe **pp, + struct dcerpc_binding *binding, + const char *pipe_uuid, + uint32_t pipe_version, + const char *domain, + const char *username, + const char *password) { NTSTATUS status; + struct dcerpc_pipe *p; + + (*pp) = NULL; if (!binding->endpoint) { DEBUG(0, ("Path to unix socket not specified\n")); return NT_STATUS_INVALID_PARAMETER; } - status = dcerpc_pipe_open_unix_stream(p, binding->endpoint); + p = dcerpc_pipe_init(NULL); + if (p == NULL) { + return NT_STATUS_NO_MEMORY; + } + + status = dcerpc_pipe_open_unix_stream(p->conn, binding->endpoint); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("Failed to open unix socket %s - %s\n", binding->endpoint, nt_errstr(status))); + talloc_free(p); return status; } - (*p)->flags = binding->flags; + p->conn->flags = binding->flags; /* remember the binding string for possible secondary connections */ - (*p)->binding_string = dcerpc_binding_string((*p), binding); + p->conn->binding_string = dcerpc_binding_string(p, binding); if (username && username[0] && (binding->flags & DCERPC_SCHANNEL_ANY)) { - status = dcerpc_bind_auth_schannel(*p, pipe_uuid, pipe_version, + status = dcerpc_bind_auth_schannel(p, pipe_uuid, pipe_version, domain, username, password); } else if (username && username[0]) { - status = dcerpc_bind_auth_ntlm(*p, pipe_uuid, pipe_version, domain, username, password); + status = dcerpc_bind_auth_ntlm(p, pipe_uuid, pipe_version, domain, username, password); } else { - status = dcerpc_bind_auth_none(*p, pipe_uuid, pipe_version); + status = dcerpc_bind_auth_none(p, pipe_uuid, pipe_version); } if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("Failed to bind to uuid %s - %s\n", - pipe_uuid, nt_errstr(status))); - dcerpc_pipe_close(*p); - *p = NULL; + DEBUG(0,("Failed to bind to uuid %s - %s\n", pipe_uuid, nt_errstr(status))); + talloc_free(p); return status; } + + (*pp) = p; - return status; + return status; } /* open a rpc connection to a rpc pipe on SMP using the binding structure to determine the endpoint and options */ -static NTSTATUS dcerpc_pipe_connect_ncacn_ip_tcp(struct dcerpc_pipe **p, +static NTSTATUS dcerpc_pipe_connect_ncacn_ip_tcp(struct dcerpc_pipe **pp, struct dcerpc_binding *binding, const char *pipe_uuid, uint32_t pipe_version, @@ -994,14 +1014,24 @@ static NTSTATUS dcerpc_pipe_connect_ncacn_ip_tcp(struct dcerpc_pipe **p, { NTSTATUS status; uint32_t port = 0; - TALLOC_CTX *mem_ctx = talloc_init("connect_ncacn_ip_tcp"); + struct dcerpc_pipe *p; + TALLOC_CTX *tmp_ctx; + + (*pp) = NULL; + + p = dcerpc_pipe_init(NULL); + if (p == NULL) { + return NT_STATUS_NO_MEMORY; + } + tmp_ctx = talloc_new(p); if (!binding->endpoint) { - status = dcerpc_epm_map_binding(mem_ctx, binding, - pipe_uuid, pipe_version); + status = dcerpc_epm_map_binding(tmp_ctx, binding, + pipe_uuid, pipe_version); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("Failed to map DCERPC/TCP port for '%s' - %s\n", pipe_uuid, nt_errstr(status))); + talloc_free(p); return status; } DEBUG(1,("Mapped to DCERPC/TCP port %s\n", binding->endpoint)); @@ -1009,34 +1039,37 @@ static NTSTATUS dcerpc_pipe_connect_ncacn_ip_tcp(struct dcerpc_pipe **p, port = atoi(binding->endpoint); - status = dcerpc_pipe_open_tcp(p, binding->host, port); + status = dcerpc_pipe_open_tcp(p->conn, binding->host, port); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("Failed to connect to %s:%d - %s\n", binding->host, port, nt_errstr(status))); + talloc_free(p); return status; } - (*p)->flags = binding->flags; + p->conn->flags = binding->flags; /* remember the binding string for possible secondary connections */ - (*p)->binding_string = dcerpc_binding_string((*p), binding); + p->conn->binding_string = dcerpc_binding_string(p, binding); if (username && username[0] && (binding->flags & DCERPC_SCHANNEL_ANY)) { - status = dcerpc_bind_auth_schannel(*p, pipe_uuid, pipe_version, + status = dcerpc_bind_auth_schannel(p, pipe_uuid, pipe_version, domain, username, password); } else if (username && username[0]) { - status = dcerpc_bind_auth_ntlm(*p, pipe_uuid, pipe_version, domain, username, password); + status = dcerpc_bind_auth_ntlm(p, pipe_uuid, pipe_version, domain, username, password); } else { - status = dcerpc_bind_auth_none(*p, pipe_uuid, pipe_version); + status = dcerpc_bind_auth_none(p, pipe_uuid, pipe_version); } if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("Failed to bind to uuid %s - %s\n", pipe_uuid, nt_errstr(status))); - dcerpc_pipe_close(*p); - *p = NULL; + talloc_free(p); return status; } + + (*pp) = p; + talloc_free(tmp_ctx); return status; } @@ -1044,7 +1077,7 @@ static NTSTATUS dcerpc_pipe_connect_ncacn_ip_tcp(struct dcerpc_pipe **p, /* open a rpc connection to a rpc pipe, using the specified binding structure to determine the endpoint and options */ -NTSTATUS dcerpc_pipe_connect_b(struct dcerpc_pipe **p, +NTSTATUS dcerpc_pipe_connect_b(struct dcerpc_pipe **pp, struct dcerpc_binding *binding, const char *pipe_uuid, uint32_t pipe_version, @@ -1056,18 +1089,20 @@ NTSTATUS dcerpc_pipe_connect_b(struct dcerpc_pipe **p, switch (binding->transport) { case NCACN_NP: - status = dcerpc_pipe_connect_ncacn_np(p, binding, pipe_uuid, pipe_version, + status = dcerpc_pipe_connect_ncacn_np(pp, binding, pipe_uuid, pipe_version, domain, username, password); break; case NCACN_IP_TCP: - status = dcerpc_pipe_connect_ncacn_ip_tcp(p, binding, pipe_uuid, pipe_version, + status = dcerpc_pipe_connect_ncacn_ip_tcp(pp, binding, pipe_uuid, pipe_version, domain, username, password); break; case NCACN_UNIX_STREAM: - status = dcerpc_pipe_connect_ncacn_unix_stream(p, binding, pipe_uuid, pipe_version, domain, username, password); + status = dcerpc_pipe_connect_ncacn_unix_stream(pp, binding, pipe_uuid, pipe_version, + domain, username, password); break; case NCALRPC: - status = dcerpc_pipe_connect_ncalrpc(p, binding, pipe_uuid, pipe_version, domain, username, password); + status = dcerpc_pipe_connect_ncalrpc(pp, binding, pipe_uuid, pipe_version, + domain, username, password); break; default: return NT_STATUS_NOT_SUPPORTED; @@ -1079,7 +1114,7 @@ NTSTATUS dcerpc_pipe_connect_b(struct dcerpc_pipe **p, /* open a rpc connection to a rpc pipe, using the specified string binding to determine the endpoint and options */ -NTSTATUS dcerpc_pipe_connect(struct dcerpc_pipe **p, +NTSTATUS dcerpc_pipe_connect(struct dcerpc_pipe **pp, const char *binding, const char *pipe_uuid, uint32_t pipe_version, @@ -1089,23 +1124,23 @@ NTSTATUS dcerpc_pipe_connect(struct dcerpc_pipe **p, { struct dcerpc_binding b; NTSTATUS status; - TALLOC_CTX *mem_ctx; + TALLOC_CTX *tmp_ctx; - mem_ctx = talloc_init("dcerpc_pipe_connect"); - if (!mem_ctx) return NT_STATUS_NO_MEMORY; + tmp_ctx = talloc_new(NULL); - status = dcerpc_parse_binding(mem_ctx, binding, &b); + status = dcerpc_parse_binding(tmp_ctx, binding, &b); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("Failed to parse dcerpc binding '%s'\n", binding)); - talloc_destroy(mem_ctx); + talloc_free(tmp_ctx); return status; } - DEBUG(3,("Using binding %s\n", dcerpc_binding_string(mem_ctx, &b))); + DEBUG(3,("Using binding %s\n", dcerpc_binding_string(tmp_ctx, &b))); - status = dcerpc_pipe_connect_b(p, &b, pipe_uuid, pipe_version, domain, username, password); + status = dcerpc_pipe_connect_b(pp, &b, pipe_uuid, pipe_version, domain, username, password); + + talloc_free(tmp_ctx); - talloc_destroy(mem_ctx); return status; } @@ -1125,32 +1160,37 @@ NTSTATUS dcerpc_secondary_connection(struct dcerpc_pipe *p, struct dcerpc_pipe * NTSTATUS status = NT_STATUS_INVALID_PARAMETER; struct dcerpc_binding b; - switch (p->transport.transport) { + (*p2) = dcerpc_pipe_init(p); + if (*p2 == NULL) { + return NT_STATUS_NO_MEMORY; + } + + switch (p->conn->transport.transport) { case NCACN_NP: - tree = dcerpc_smb_tree(p); + tree = dcerpc_smb_tree(p->conn); if (!tree) { return NT_STATUS_INVALID_PARAMETER; } - status = dcerpc_pipe_open_smb(p2, tree, pipe_name); + status = dcerpc_pipe_open_smb((*p2)->conn, tree, pipe_name); break; case NCACN_IP_TCP: - status = dcerpc_parse_binding(p, p->binding_string, &b); + status = dcerpc_parse_binding(p, p->conn->binding_string, &b); if (!NT_STATUS_IS_OK(status)) { return status; } b.flags &= ~DCERPC_AUTH_OPTIONS; - status = dcerpc_pipe_open_tcp(p2, b.host, atoi(b.endpoint)); + status = dcerpc_pipe_open_tcp((*p2)->conn, b.host, atoi(b.endpoint)); break; case NCALRPC: - status = dcerpc_parse_binding(p, p->binding_string, &b); + status = dcerpc_parse_binding(p, p->conn->binding_string, &b); if (!NT_STATUS_IS_OK(status)) { return status; } b.flags &= ~DCERPC_AUTH_OPTIONS; - status = dcerpc_pipe_open_pipe(p2, b.endpoint); + status = dcerpc_pipe_open_pipe((*p2)->conn, b.endpoint); break; default: @@ -1158,22 +1198,22 @@ NTSTATUS dcerpc_secondary_connection(struct dcerpc_pipe *p, struct dcerpc_pipe * } if (!NT_STATUS_IS_OK(status)) { + talloc_free(*p2); return status; } - talloc_steal(p, *p2); - - (*p2)->flags = p->flags; + (*p2)->conn->flags = p->conn->flags; status = dcerpc_bind_auth_none(*p2, pipe_uuid, pipe_version); if (!NT_STATUS_IS_OK(status)) { + talloc_free(*p2); return status; } return NT_STATUS_OK; } -NTSTATUS dcerpc_generic_session_key(struct dcerpc_pipe *p, +NTSTATUS dcerpc_generic_session_key(struct dcerpc_connection *c, DATA_BLOB *session_key) { /* this took quite a few CPU cycles to find ... */ @@ -1188,7 +1228,7 @@ NTSTATUS dcerpc_generic_session_key(struct dcerpc_pipe *p, NTSTATUS dcerpc_fetch_session_key(struct dcerpc_pipe *p, DATA_BLOB *session_key) { - return p->security_state.session_key(p, session_key); + return p->conn->security_state.session_key(p->conn, session_key); } -- cgit