summaryrefslogtreecommitdiff
path: root/source4/rpc_server
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2010-10-30 11:33:53 +1100
committerAndrew Tridgell <tridge@samba.org>2010-10-30 23:49:01 +1100
commit0563c5bacf96d1b6759acd78377c417715f30fff (patch)
treeb769f62de7a337fa42c3e9f7648d0a7e3b639c50 /source4/rpc_server
parentac8e9106862fc4d49c070d3d307f43df9d7cc842 (diff)
downloadsamba-0563c5bacf96d1b6759acd78377c417715f30fff.tar.gz
samba-0563c5bacf96d1b6759acd78377c417715f30fff.tar.bz2
samba-0563c5bacf96d1b6759acd78377c417715f30fff.zip
s4-rpc: split the dcesrv reply code out of dcerpc_server
this allows us to remove a dependency on the dcerpc_server from code that uses rpc forwarding Pair-Programmed-With: Andrew Bartlett <abartlet@samba.org>
Diffstat (limited to 'source4/rpc_server')
-rw-r--r--source4/rpc_server/common/forward.c1
-rw-r--r--source4/rpc_server/common/reply.c254
-rw-r--r--source4/rpc_server/dcerpc_server.c172
-rw-r--r--source4/rpc_server/dcesrv_auth.c1
-rw-r--r--source4/rpc_server/wscript_build8
5 files changed, 261 insertions, 175 deletions
diff --git a/source4/rpc_server/common/forward.c b/source4/rpc_server/common/forward.c
index 113ac5f6c4..45ce6dcac9 100644
--- a/source4/rpc_server/common/forward.c
+++ b/source4/rpc_server/common/forward.c
@@ -22,6 +22,7 @@
#include "includes.h"
#include <tevent.h>
#include "rpc_server/dcerpc_server.h"
+#include "librpc/gen_ndr/dcerpc.h"
#include "rpc_server/common/common.h"
#include "messaging/irpc.h"
#include "auth/auth.h"
diff --git a/source4/rpc_server/common/reply.c b/source4/rpc_server/common/reply.c
new file mode 100644
index 0000000000..d883317d6e
--- /dev/null
+++ b/source4/rpc_server/common/reply.c
@@ -0,0 +1,254 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ server side dcerpc common code
+
+ Copyright (C) Andrew Tridgell 2003-2010
+ Copyright (C) Stefan (metze) Metzmacher 2004-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
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "auth/auth.h"
+#include "auth/gensec/gensec.h"
+#include "../lib/util/dlinklist.h"
+#include "rpc_server/dcerpc_server.h"
+#include "rpc_server/dcerpc_server_proto.h"
+#include "rpc_server/common/proto.h"
+#include "librpc/rpc/dcerpc_proto.h"
+#include "system/filesys.h"
+#include "libcli/security/security.h"
+#include "param/param.h"
+#include "../lib/tsocket/tsocket.h"
+#include "../libcli/named_pipe_auth/npa_tstream.h"
+#include "smbd/service_stream.h"
+#include "../lib/tsocket/tsocket.h"
+#include "lib/socket/socket.h"
+#include "smbd/process_model.h"
+#include "lib/messaging/irpc.h"
+
+
+/*
+ move a call from an existing linked list to the specified list. This
+ prevents bugs where we forget to remove the call from a previous
+ list when moving it.
+ */
+static void dcesrv_call_set_list(struct dcesrv_call_state *call,
+ enum dcesrv_call_list list)
+{
+ switch (call->list) {
+ case DCESRV_LIST_NONE:
+ break;
+ case DCESRV_LIST_CALL_LIST:
+ DLIST_REMOVE(call->conn->call_list, call);
+ break;
+ case DCESRV_LIST_FRAGMENTED_CALL_LIST:
+ DLIST_REMOVE(call->conn->incoming_fragmented_call_list, call);
+ break;
+ case DCESRV_LIST_PENDING_CALL_LIST:
+ DLIST_REMOVE(call->conn->pending_call_list, call);
+ break;
+ }
+ call->list = list;
+ switch (list) {
+ case DCESRV_LIST_NONE:
+ break;
+ case DCESRV_LIST_CALL_LIST:
+ DLIST_ADD_END(call->conn->call_list, call, struct dcesrv_call_state *);
+ break;
+ case DCESRV_LIST_FRAGMENTED_CALL_LIST:
+ DLIST_ADD_END(call->conn->incoming_fragmented_call_list, call, struct dcesrv_call_state *);
+ break;
+ case DCESRV_LIST_PENDING_CALL_LIST:
+ DLIST_ADD_END(call->conn->pending_call_list, call, struct dcesrv_call_state *);
+ break;
+ }
+}
+
+
+void dcesrv_init_hdr(struct ncacn_packet *pkt, bool bigendian)
+{
+ pkt->rpc_vers = 5;
+ pkt->rpc_vers_minor = 0;
+ if (bigendian) {
+ pkt->drep[0] = 0;
+ } else {
+ pkt->drep[0] = DCERPC_DREP_LE;
+ }
+ pkt->drep[1] = 0;
+ pkt->drep[2] = 0;
+ pkt->drep[3] = 0;
+}
+
+
+/*
+ return a dcerpc fault
+*/
+NTSTATUS dcesrv_fault(struct dcesrv_call_state *call, uint32_t fault_code)
+{
+ struct ncacn_packet pkt;
+ struct data_blob_list_item *rep;
+ uint8_t zeros[4];
+ NTSTATUS status;
+
+ /* setup a bind_ack */
+ dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
+ pkt.auth_length = 0;
+ pkt.call_id = call->pkt.call_id;
+ pkt.ptype = DCERPC_PKT_FAULT;
+ pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
+ pkt.u.fault.alloc_hint = 0;
+ pkt.u.fault.context_id = 0;
+ pkt.u.fault.cancel_count = 0;
+ pkt.u.fault.status = fault_code;
+
+ ZERO_STRUCT(zeros);
+ pkt.u.fault._pad = data_blob_const(zeros, sizeof(zeros));
+
+ rep = talloc(call, struct data_blob_list_item);
+ if (!rep) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ status = ncacn_push_auth(&rep->blob, call, &pkt, NULL);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ dcerpc_set_frag_length(&rep->blob, rep->blob.length);
+
+ DLIST_ADD_END(call->replies, rep, struct data_blob_list_item *);
+ dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
+
+ if (call->conn->call_list && call->conn->call_list->replies) {
+ if (call->conn->transport.report_output_data) {
+ call->conn->transport.report_output_data(call->conn);
+ }
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+
+_PUBLIC_ NTSTATUS dcesrv_reply(struct dcesrv_call_state *call)
+{
+ struct ndr_push *push;
+ NTSTATUS status;
+ DATA_BLOB stub;
+ uint32_t total_length, chunk_size;
+ struct dcesrv_connection_context *context = call->context;
+ size_t sig_size = 0;
+
+ /* call the reply function */
+ status = context->iface->reply(call, call, call->r);
+ if (!NT_STATUS_IS_OK(status)) {
+ return dcesrv_fault(call, call->fault_code);
+ }
+
+ /* form the reply NDR */
+ push = ndr_push_init_ctx(call);
+ NT_STATUS_HAVE_NO_MEMORY(push);
+
+ /* carry over the pointer count to the reply in case we are
+ using full pointer. See NDR specification for full
+ pointers */
+ push->ptr_count = call->ndr_pull->ptr_count;
+
+ if (lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx)) {
+ push->flags |= LIBNDR_FLAG_BIGENDIAN;
+ }
+
+ status = context->iface->ndr_push(call, call, push, call->r);
+ if (!NT_STATUS_IS_OK(status)) {
+ return dcesrv_fault(call, call->fault_code);
+ }
+
+ stub = ndr_push_blob(push);
+
+ total_length = stub.length;
+
+ /* we can write a full max_recv_frag size, minus the dcerpc
+ request header size */
+ chunk_size = call->conn->cli_max_recv_frag;
+ chunk_size -= DCERPC_REQUEST_LENGTH;
+ if (call->conn->auth_state.auth_info &&
+ call->conn->auth_state.gensec_security) {
+ sig_size = gensec_sig_size(call->conn->auth_state.gensec_security,
+ call->conn->cli_max_recv_frag);
+ if (sig_size) {
+ chunk_size -= DCERPC_AUTH_TRAILER_LENGTH;
+ chunk_size -= sig_size;
+ }
+ }
+ chunk_size -= (chunk_size % 16);
+
+ do {
+ uint32_t length;
+ struct data_blob_list_item *rep;
+ struct ncacn_packet pkt;
+
+ rep = talloc(call, struct data_blob_list_item);
+ NT_STATUS_HAVE_NO_MEMORY(rep);
+
+ length = MIN(chunk_size, stub.length);
+
+ /* form the dcerpc response packet */
+ dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
+ pkt.auth_length = 0;
+ pkt.call_id = call->pkt.call_id;
+ pkt.ptype = DCERPC_PKT_RESPONSE;
+ pkt.pfc_flags = 0;
+ if (stub.length == total_length) {
+ pkt.pfc_flags |= DCERPC_PFC_FLAG_FIRST;
+ }
+ if (length == stub.length) {
+ pkt.pfc_flags |= DCERPC_PFC_FLAG_LAST;
+ }
+ pkt.u.response.alloc_hint = stub.length;
+ pkt.u.response.context_id = call->pkt.u.request.context_id;
+ pkt.u.response.cancel_count = 0;
+ pkt.u.response.stub_and_verifier.data = stub.data;
+ pkt.u.response.stub_and_verifier.length = length;
+
+ if (!dcesrv_auth_response(call, &rep->blob, sig_size, &pkt)) {
+ return dcesrv_fault(call, DCERPC_FAULT_OTHER);
+ }
+
+ dcerpc_set_frag_length(&rep->blob, rep->blob.length);
+
+ DLIST_ADD_END(call->replies, rep, struct data_blob_list_item *);
+
+ stub.data += length;
+ stub.length -= length;
+ } while (stub.length != 0);
+
+ /* move the call from the pending to the finished calls list */
+ dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
+
+ if (call->conn->call_list && call->conn->call_list->replies) {
+ if (call->conn->transport.report_output_data) {
+ call->conn->transport.report_output_data(call->conn);
+ }
+ }
+
+ return NT_STATUS_OK;
+}
+
+NTSTATUS dcesrv_generic_session_key(struct dcesrv_connection *c,
+ DATA_BLOB *session_key)
+{
+ return dcerpc_generic_session_key(NULL, session_key);
+}
diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c
index dc3b9bcfd6..1741b59929 100644
--- a/source4/rpc_server/dcerpc_server.c
+++ b/source4/rpc_server/dcerpc_server.c
@@ -26,6 +26,7 @@
#include "../lib/util/dlinklist.h"
#include "rpc_server/dcerpc_server.h"
#include "rpc_server/dcerpc_server_proto.h"
+#include "rpc_server/common/proto.h"
#include "librpc/rpc/dcerpc_proto.h"
#include "system/filesys.h"
#include "libcli/security/security.h"
@@ -338,12 +339,6 @@ NTSTATUS dcesrv_inherited_session_key(struct dcesrv_connection *p,
return NT_STATUS_NO_USER_SESSION_KEY;
}
-NTSTATUS dcesrv_generic_session_key(struct dcesrv_connection *c,
- DATA_BLOB *session_key)
-{
- return dcerpc_generic_session_key(NULL, session_key);
-}
-
/*
fetch the user session key - may be default (above) or the SMB session key
@@ -413,20 +408,6 @@ _PUBLIC_ NTSTATUS dcesrv_endpoint_connect(struct dcesrv_context *dce_ctx,
return NT_STATUS_OK;
}
-static void dcesrv_init_hdr(struct ncacn_packet *pkt, bool bigendian)
-{
- pkt->rpc_vers = 5;
- pkt->rpc_vers_minor = 0;
- if (bigendian) {
- pkt->drep[0] = 0;
- } else {
- pkt->drep[0] = DCERPC_DREP_LE;
- }
- pkt->drep[1] = 0;
- pkt->drep[2] = 0;
- pkt->drep[3] = 0;
-}
-
/*
move a call from an existing linked list to the specified list. This
prevents bugs where we forget to remove the call from a previous
@@ -464,54 +445,6 @@ static void dcesrv_call_set_list(struct dcesrv_call_state *call,
}
}
-/*
- return a dcerpc fault
-*/
-static NTSTATUS dcesrv_fault(struct dcesrv_call_state *call, uint32_t fault_code)
-{
- struct ncacn_packet pkt;
- struct data_blob_list_item *rep;
- uint8_t zeros[4];
- NTSTATUS status;
-
- /* setup a bind_ack */
- dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
- pkt.auth_length = 0;
- pkt.call_id = call->pkt.call_id;
- pkt.ptype = DCERPC_PKT_FAULT;
- pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
- pkt.u.fault.alloc_hint = 0;
- pkt.u.fault.context_id = 0;
- pkt.u.fault.cancel_count = 0;
- pkt.u.fault.status = fault_code;
-
- ZERO_STRUCT(zeros);
- pkt.u.fault._pad = data_blob_const(zeros, sizeof(zeros));
-
- rep = talloc(call, struct data_blob_list_item);
- if (!rep) {
- return NT_STATUS_NO_MEMORY;
- }
-
- status = ncacn_push_auth(&rep->blob, call, &pkt, NULL);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- dcerpc_set_frag_length(&rep->blob, rep->blob.length);
-
- DLIST_ADD_END(call->replies, rep, struct data_blob_list_item *);
- dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
-
- if (call->conn->call_list && call->conn->call_list->replies) {
- if (call->conn->transport.report_output_data) {
- call->conn->transport.report_output_data(call->conn);
- }
- }
-
- return NT_STATUS_OK;
-}
-
/*
return a dcerpc bind_nak
@@ -1046,109 +979,6 @@ static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
return dcesrv_reply(call);
}
-_PUBLIC_ NTSTATUS dcesrv_reply(struct dcesrv_call_state *call)
-{
- struct ndr_push *push;
- NTSTATUS status;
- DATA_BLOB stub;
- uint32_t total_length, chunk_size;
- struct dcesrv_connection_context *context = call->context;
- size_t sig_size = 0;
-
- /* call the reply function */
- status = context->iface->reply(call, call, call->r);
- if (!NT_STATUS_IS_OK(status)) {
- return dcesrv_fault(call, call->fault_code);
- }
-
- /* form the reply NDR */
- push = ndr_push_init_ctx(call);
- NT_STATUS_HAVE_NO_MEMORY(push);
-
- /* carry over the pointer count to the reply in case we are
- using full pointer. See NDR specification for full
- pointers */
- push->ptr_count = call->ndr_pull->ptr_count;
-
- if (lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx)) {
- push->flags |= LIBNDR_FLAG_BIGENDIAN;
- }
-
- status = context->iface->ndr_push(call, call, push, call->r);
- if (!NT_STATUS_IS_OK(status)) {
- return dcesrv_fault(call, call->fault_code);
- }
-
- stub = ndr_push_blob(push);
-
- total_length = stub.length;
-
- /* we can write a full max_recv_frag size, minus the dcerpc
- request header size */
- chunk_size = call->conn->cli_max_recv_frag;
- chunk_size -= DCERPC_REQUEST_LENGTH;
- if (call->conn->auth_state.auth_info &&
- call->conn->auth_state.gensec_security) {
- sig_size = gensec_sig_size(call->conn->auth_state.gensec_security,
- call->conn->cli_max_recv_frag);
- if (sig_size) {
- chunk_size -= DCERPC_AUTH_TRAILER_LENGTH;
- chunk_size -= sig_size;
- }
- }
- chunk_size -= (chunk_size % 16);
-
- do {
- uint32_t length;
- struct data_blob_list_item *rep;
- struct ncacn_packet pkt;
-
- rep = talloc(call, struct data_blob_list_item);
- NT_STATUS_HAVE_NO_MEMORY(rep);
-
- length = MIN(chunk_size, stub.length);
-
- /* form the dcerpc response packet */
- dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
- pkt.auth_length = 0;
- pkt.call_id = call->pkt.call_id;
- pkt.ptype = DCERPC_PKT_RESPONSE;
- pkt.pfc_flags = 0;
- if (stub.length == total_length) {
- pkt.pfc_flags |= DCERPC_PFC_FLAG_FIRST;
- }
- if (length == stub.length) {
- pkt.pfc_flags |= DCERPC_PFC_FLAG_LAST;
- }
- pkt.u.response.alloc_hint = stub.length;
- pkt.u.response.context_id = call->pkt.u.request.context_id;
- pkt.u.response.cancel_count = 0;
- pkt.u.response.stub_and_verifier.data = stub.data;
- pkt.u.response.stub_and_verifier.length = length;
-
- if (!dcesrv_auth_response(call, &rep->blob, sig_size, &pkt)) {
- return dcesrv_fault(call, DCERPC_FAULT_OTHER);
- }
-
- dcerpc_set_frag_length(&rep->blob, rep->blob.length);
-
- DLIST_ADD_END(call->replies, rep, struct data_blob_list_item *);
-
- stub.data += length;
- stub.length -= length;
- } while (stub.length != 0);
-
- /* move the call from the pending to the finished calls list */
- dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
-
- if (call->conn->call_list && call->conn->call_list->replies) {
- if (call->conn->transport.report_output_data) {
- call->conn->transport.report_output_data(call->conn);
- }
- }
-
- return NT_STATUS_OK;
-}
/*
remove the call from the right list when freed
diff --git a/source4/rpc_server/dcesrv_auth.c b/source4/rpc_server/dcesrv_auth.c
index 3140598fec..c7f3cdecc1 100644
--- a/source4/rpc_server/dcesrv_auth.c
+++ b/source4/rpc_server/dcesrv_auth.c
@@ -23,6 +23,7 @@
#include "includes.h"
#include "rpc_server/dcerpc_server.h"
#include "rpc_server/dcerpc_server_proto.h"
+#include "rpc_server/common/proto.h"
#include "librpc/rpc/dcerpc_proto.h"
#include "librpc/gen_ndr/ndr_dcerpc.h"
#include "auth/credentials/credentials.h"
diff --git a/source4/rpc_server/wscript_build b/source4/rpc_server/wscript_build
index 81a6a9f8c2..742982edfb 100644
--- a/source4/rpc_server/wscript_build
+++ b/source4/rpc_server/wscript_build
@@ -7,7 +7,7 @@ bld.SAMBA_SUBSYSTEM('DCERPC_SHARE',
)
bld.SAMBA_SUBSYSTEM('DCERPC_COMMON',
- source='common/forward.c',
+ source='common/forward.c common/reply.c dcesrv_auth.c',
autoproto='common/proto.h',
public_headers='common/common.h',
header_path='dcerpc_server',
@@ -131,7 +131,7 @@ bld.SAMBA_MODULE('dcerpc_eventlog',
)
bld.SAMBA_LIBRARY('dcerpc_server',
- source='dcerpc_server.c dcesrv_auth.c dcesrv_mgmt.c handles.c',
+ source='dcerpc_server.c dcesrv_mgmt.c handles.c',
pc_files='dcerpc_server.pc',
deps='LIBCLI_AUTH ndr samba_server_gensec dcerpc_remote service',
public_deps='dcerpc',
@@ -140,12 +140,12 @@ bld.SAMBA_LIBRARY('dcerpc_server',
vnum='0.0.1'
)
-bld.SAMBA_MODULE('DCESRV',
+bld.SAMBA_MODULE('dcesrv',
source='service_rpc.c',
autoproto='service_rpc.h',
subsystem='service',
init_function='server_service_rpc_init',
- internal_module=True,
+ internal_module=False,
deps='dcerpc_server'
)