s4-rpc: split the dcesrv reply code out of dcerpc_server
authorAndrew Tridgell <tridge@samba.org>
Sat, 30 Oct 2010 00:33:53 +0000 (11:33 +1100)
committerAndrew Tridgell <tridge@samba.org>
Sat, 30 Oct 2010 12:49:01 +0000 (23:49 +1100)
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>

source4/ntptr/simple_ldb/ntptr_simple_ldb.c
source4/ntvfs/ipc/rap_server.c
source4/rpc_server/common/forward.c
source4/rpc_server/common/reply.c [new file with mode: 0644]
source4/rpc_server/dcerpc_server.c
source4/rpc_server/dcesrv_auth.c
source4/rpc_server/wscript_build

index 2790f8359d613aee8f53eadf4d9449e887cda804..641f5d3959e4acf751e02bd8ae087b36c286f394 100644 (file)
@@ -35,6 +35,8 @@
 #include "dsdb/samdb/samdb.h"
 #include "ldb_wrap.h"
 #include "../lib/util/util_ldb.h"
+#include "librpc/gen_ndr/dcerpc.h"
+#include "rpc_server/dcerpc_server.h"
 #include "rpc_server/common/common.h"
 #include "param/param.h"
 
index dbd1fccfea8bcce877bebfb19c23af945dfa58ea..8f36c09ebcac96fbaf062be9ab87b21efc6efec4 100644 (file)
@@ -23,6 +23,7 @@
 #include "../librpc/gen_ndr/rap.h"
 #include "libcli/raw/interfaces.h"
 #include "librpc/gen_ndr/srvsvc.h"
+#include "librpc/gen_ndr/dcerpc.h"
 #include "rpc_server/common/common.h"
 #include "rpc_server/common/share.h"
 #include "param/param.h"
index 113ac5f6c467e8f88e03bf31582cca436780f224..45ce6dcac93b4fd46a919f83412aba04581f10b0 100644 (file)
@@ -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 (file)
index 0000000..d883317
--- /dev/null
@@ -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);
+}
index dc3b9bcfd6ac8fc15096ed3458c5e1d689c7900b..1741b599294769e04f93d08240c722fe074bbc05 100644 (file)
@@ -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
index 3140598fecc30f3df9c9e82f59feaa54f680f3d8..c7f3cdecc15d72bb9dba3a7faf56b5fb6b96b4e8 100644 (file)
@@ -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"
index 81a6a9f8c2c3b9b9f62c6842e60c558a76f7f66f..742982edfb46c9f29d00a37fe0d85ae0795e32d0 100644 (file)
@@ -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'
        )