[PATCH][WIP] Make the Samba AD DC multi-process

Stefan Metzmacher metze at samba.org
Mon Dec 19 22:03:23 UTC 2016


Am 19.12.2016 um 11:36 schrieb Andrew Bartlett:
> On Thu, 2016-12-15 at 04:00 +1300, Andrew Bartlett wrote:
>> On Wed, 2016-12-14 at 12:08 +0100, Stefan Metzmacher wrote:
>>>  
>>> I've pushed the torture tests alone as I want to make sure we
>>> already
>>> pass them (as we should) with the current code.
>>
>> Good idea.  I just ran out of work day to re-order, so thanks!
>>
>>>
>>> I'd push the "rpc_server:netlogon Move from memcache to a tdb
>>> cache"
>>> patch with the following additions squashed:
>>> https://git.samba.org/?p=metze/samba/wip.git;a=commitdiff;h=7b19da5
>>> 51
>>> 6a63126cb087403057639cca600fc10
>>
>> Thanks.
>>
>>>
>>> Then I'll push the "lsa over netlogon" patches alone.
>>
>> Great.
>>
>>>
>>> I still think we should not handle
>>> DCESRV_INTERFACE_FLAGS_HANDLES_NOT_USED
>>> in dcesrv_handle_fetch(), if you want to add something
>>> let dcesrv_handle_new() fail and make sure all callers
>>> of dcesrv_handle_new() check the return.
> 
> I've added an SMB_ASSERT() to both calls.  I hope this is an acceptable
> approach, otherwise please just ignore this patch, it isn't worth going
> over and over again compared to the other things we need to sort out
> this week. 

Thanks!

>>> And before calling dcesrv_add_ep() we should
>>> set e->use_single_process = true if this_model_ops is
>>> the same as model_ops. If someone uses samba -Msingle
>>> e->use_single_process should always be true.
>>
>> OK, that makes a little more sense to me now.  Could you do that for
>> me?  (Otherwise I'll get to it next week).
> 
> I've added that.  Can you please review the attached, or at least
> indicate I've met your objections?

Almost, but there're still minor things to fix, see the TODO
comments in the commit messages.

metze
-------------- next part --------------
From a75a911e92abc8e861fbd13c42aa1f800543d9ed Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Tue, 18 Oct 2016 10:36:51 +1300
Subject: [PATCH 1/6] TODO: s4-rpc_server: Allow listener for RPC servers to
 use multiple processes

To do this we must get the ncacn_ip_tcp listener to split out (for example)
netlogon onto a distinct port, so we change the registration code to split up each
ncacn_ip_tcp registration to create a new interface for indicated services.

The new option "rpc server port" allows control of the default port and
"rpc server port:netlogon" (also valid for any other pipe from the IDL name)
allows us to both work around limitations in socket_wrapper against
double-binding and allows specification of the port by the administrator.

Signed-off-by: Andrew Bartlett <abartlet at samba.org>

TODO: dcesrv_interface_register() needs to check if the endpoint already
has a hardcoded value, e.g. port 135 (ncacn_ip_tcp:[135])

TODO: don't use '== true' or '== false', just 'if (boolvar)' or 'if (!boolvar)'

TODO: this doesn't need a new line after '='
+       transport =
+               dcerpc_binding_get_transport(binding);
---
 docs-xml/smbdotconf/protocol/rpcserverport.xml |  14 +++
 source4/rpc_server/dcerpc_server.c             | 121 +++++++++++++++++++++----
 source4/rpc_server/dcerpc_server.h             |   6 ++
 source4/rpc_server/service_rpc.c               |  42 +++++++--
 4 files changed, 159 insertions(+), 24 deletions(-)
 create mode 100644 docs-xml/smbdotconf/protocol/rpcserverport.xml

diff --git a/docs-xml/smbdotconf/protocol/rpcserverport.xml b/docs-xml/smbdotconf/protocol/rpcserverport.xml
new file mode 100644
index 0000000..8a70835
--- /dev/null
+++ b/docs-xml/smbdotconf/protocol/rpcserverport.xml
@@ -0,0 +1,14 @@
+<samba:parameter name="rpc server port"
+                 context="G"
+                 type="integer"
+                 xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
+<description>
+	<para>Specifies which port the server should listen on for DCE/RPC over TCP/IP traffic.</para>
+	<para>This controls default port for all protocols, except for NETLOGON.  If unset, the first available port after 1024 is used.</para>
+	<para>The NETLOGON server will use the next available port, eg 1025.  To change this port use (eg) rpc server port:netlogon = 4000.</para>
+	<para>Furthermore, all RPC servers can have the port they use specified independenty, with (for example) rpc server port:drsuapi = 5000.</para>
+
+</description>
+<para>The default value 0 causes Samba to select the first available port after 1024.</para>
+<value type="default">0</value>
+</samba:parameter>
diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c
index 0d39744..fed4c29 100644
--- a/source4/rpc_server/dcerpc_server.c
+++ b/source4/rpc_server/dcerpc_server.c
@@ -190,15 +190,21 @@ static bool interface_match(const struct dcesrv_interface *if1,
 }
 
 /*
-  find the interface operations on an endpoint
+  find the interface operations on any endpoint with this binding
 */
-static const struct dcesrv_interface *find_interface(const struct dcesrv_endpoint *endpoint,
-						     const struct dcesrv_interface *iface)
+static const struct dcesrv_interface *find_interface_by_binding(struct dcesrv_context *dce_ctx,
+								struct dcerpc_binding *binding,
+								const struct dcesrv_interface *iface)
 {
-	struct dcesrv_if_list *ifl;
-	for (ifl=endpoint->interface_list; ifl; ifl=ifl->next) {
-		if (interface_match(&(ifl->iface), iface)) {
-			return &(ifl->iface);
+	struct dcesrv_endpoint *ep;
+	for (ep=dce_ctx->endpoint_list; ep; ep=ep->next) {
+		if (endpoints_match(ep->ep_description, binding)) {
+			struct dcesrv_if_list *ifl;
+			for (ifl=ep->interface_list; ifl; ifl=ifl->next) {
+				if (interface_match(&(ifl->iface), iface)) {
+					return &(ifl->iface);
+				}
+			}
 		}
 	}
 	return NULL;
@@ -217,8 +223,8 @@ static bool interface_match_by_uuid(const struct dcesrv_interface *iface,
 /*
   find the interface operations on an endpoint by uuid
 */
-static const struct dcesrv_interface *find_interface_by_uuid(const struct dcesrv_endpoint *endpoint,
-							     const struct GUID *uuid, uint32_t if_version)
+const struct dcesrv_interface *find_interface_by_uuid(const struct dcesrv_endpoint *endpoint,
+						      const struct GUID *uuid, uint32_t if_version)
 {
 	struct dcesrv_if_list *ifl;
 	for (ifl=endpoint->interface_list; ifl; ifl=ifl->next) {
@@ -245,6 +251,15 @@ static struct dcesrv_call_state *dcesrv_find_fragmented_call(struct dcesrv_conne
 
 /*
   register an interface on an endpoint
+
+  An endpoint is one unix domain socket (for ncalrpc), one TCP port
+  (for ncacn_ip_tcp) or one (forwarded) named pipe (for ncacn_np).
+
+  Each endpoint can have many interfaces such as netlogon, lsa or
+  samr.  Some have essentially the full set.
+
+  This is driven from the set of interfaces listed in each IDL file
+  via the PIDL generated *__op_init_server() functions.
 */
 _PUBLIC_ NTSTATUS dcesrv_interface_register(struct dcesrv_context *dce_ctx,
 				   const char *ep_name,
@@ -256,6 +271,9 @@ _PUBLIC_ NTSTATUS dcesrv_interface_register(struct dcesrv_context *dce_ctx,
 	struct dcerpc_binding *binding;
 	bool add_ep = false;
 	NTSTATUS status;
+	enum dcerpc_transport_t transport;
+	char *ep_string = NULL;
+	bool use_single_process = true;
 	
 	status = dcerpc_parse_binding(dce_ctx, ep_name, &binding);
 
@@ -264,9 +282,61 @@ _PUBLIC_ NTSTATUS dcesrv_interface_register(struct dcesrv_context *dce_ctx,
 		return status;
 	}
 
+	transport =
+		dcerpc_binding_get_transport(binding);
+	if (transport == NCACN_IP_TCP) {
+		int port;
+		char port_str[6];
+		port = lpcfg_parm_int(dce_ctx->lp_ctx, NULL,
+				      "rpc server port", iface->name, 0);
+
+		/*
+		 * For RPC services that are not set to use a single
+		 * process, we do not default to using the 'rpc server
+		 * port' because that would cause a double-bind on
+		 * that port.
+		 */
+		if (port == 0 && use_single_process == false) {
+			port = lpcfg_rpc_server_port(dce_ctx->lp_ctx);
+		}
+		if (port != 0) {
+			snprintf(port_str, sizeof(port_str), "%u", port);
+			status = dcerpc_binding_set_string_option(binding,
+								  "endpoint", port_str);
+			if (!NT_STATUS_IS_OK(status)) {
+				return status;
+			}
+		}
+	}
+
+	/* see if the interface is already registered on the endpoint */
+	if (find_interface_by_binding(dce_ctx, binding, iface)!=NULL) {
+		DEBUG(0,("dcesrv_interface_register: interface '%s' already registered on endpoint '%s'\n",
+			 iface->name, ep_name));
+		return NT_STATUS_OBJECT_NAME_COLLISION;
+	}
+
 	/* check if this endpoint exists
 	 */
-	if ((ep=find_endpoint(dce_ctx, binding))==NULL) {
+	ep = find_endpoint(dce_ctx, binding);
+
+	if (ep != NULL) {
+		/*
+		 * We want a new port on ncacn_ip_tcp for NETLOGON, so
+		 * it can be multi-process.  Other processes can also
+		 * listen on distinct ports, if they have one forced
+		 * in the code above with eg 'rpc server port:drsuapi = 1027'
+		 *
+		 * If we have mulitiple endpoints on port 0, they each
+		 * get an epemeral port (currently by walking up from
+		 * 1024).
+		 */
+		if (use_single_process == false && transport == NCACN_IP_TCP) {
+			add_ep = true;
+		}
+	}
+
+	if (ep == NULL || add_ep == true) {
 		ep = talloc_zero(dce_ctx, struct dcesrv_endpoint);
 		if (!ep) {
 			return NT_STATUS_NO_MEMORY;
@@ -286,11 +356,16 @@ _PUBLIC_ NTSTATUS dcesrv_interface_register(struct dcesrv_context *dce_ctx,
 		DLIST_ADD(ep->interface_list, ifl);
 	}
 
-	/* see if the interface is already registered on te endpoint */
-	if (find_interface(ep, iface)!=NULL) {
-		DEBUG(0,("dcesrv_interface_register: interface '%s' already registered on endpoint '%s'\n",
-			iface->name, ep_name));
-		return NT_STATUS_OBJECT_NAME_COLLISION;
+	/*
+	 * By default don't force into a single process, but if any
+	 * interface on this endpoint on this service uses handles
+	 * (most do), then we must force into single process mode
+	 *
+	 * By overwriting this each time a new interface is added to
+	 * this endpoint, we end up with the most restrictive setting.
+	 */
+	if (use_single_process == true) {
+		ep->use_single_process = true;
 	}
 
 	/* talloc a new interface list element */
@@ -335,8 +410,12 @@ _PUBLIC_ NTSTATUS dcesrv_interface_register(struct dcesrv_context *dce_ctx,
 		DLIST_ADD(dce_ctx->endpoint_list, ep);
 	}
 
+	/* Re-get the string as we may have set a port */
+	ep_string = dcerpc_binding_string(dce_ctx, ep->ep_description);
+
 	DEBUG(4,("dcesrv_interface_register: interface '%s' registered on endpoint '%s'\n",
-		iface->name, ep_name));
+		 iface->name, ep_string));
+	TALLOC_FREE(ep_string);
 
 	return NT_STATUS_OK;
 }
@@ -2600,8 +2679,14 @@ static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx, struct
 				     lpcfg_socket_options(dce_ctx->lp_ctx),
 				     dcesrv_sock);
 	if (!NT_STATUS_IS_OK(status)) {
-		DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) failed - %s\n", 
-			 address, port, nt_errstr(status)));
+		struct dcesrv_if_list *iface;
+		DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) for ",
+			 address, port));
+		for (iface = e->interface_list; iface; iface = iface->next) {
+			DEBUGADD(0, ("%s ", iface->iface.name));
+		}
+		DEBUGADD(0, ("failed - %s",
+			     nt_errstr(status)));
 		return status;
 	}
 
diff --git a/source4/rpc_server/dcerpc_server.h b/source4/rpc_server/dcerpc_server.h
index a1eddbc..8905c5d 100644
--- a/source4/rpc_server/dcerpc_server.h
+++ b/source4/rpc_server/dcerpc_server.h
@@ -343,6 +343,12 @@ struct dcesrv_context {
 			struct dcesrv_if_list *next, *prev;
 			struct dcesrv_interface iface;
 		} *interface_list;
+
+		/*
+		 * Should this service be run in a single process (so far only
+		 * NETLOGON is not run in a single process)
+		 */
+		bool use_single_process;
 	} *endpoint_list;
 
 	/* loadparm context to use for this connection */
diff --git a/source4/rpc_server/service_rpc.c b/source4/rpc_server/service_rpc.c
index 95f5e42..63418f4 100644
--- a/source4/rpc_server/service_rpc.c
+++ b/source4/rpc_server/service_rpc.c
@@ -49,16 +49,21 @@ static void dcesrv_task_init(struct task_server *task)
 	NTSTATUS status;
 	struct dcesrv_context *dce_ctx;
 	struct dcesrv_endpoint *e;
-	const struct model_ops *model_ops;
+	const struct model_ops *single_model_ops;
 
 	dcerpc_server_init(task->lp_ctx);
 
 	task_server_set_title(task, "task[dcesrv]");
 
-	/* run the rpc server as a single process to allow for shard
-	 * handles, and sharing of ldb contexts */
-	model_ops = process_model_startup("single");
-	if (!model_ops) goto failed;
+	/*
+	 * run the rpc server as a single process to allow for shard
+	 * handles, and sharing of ldb contexts.
+	 *
+	 * We make an exception for NETLOGON below, and this follows
+	 * whatever the top level is.
+	 */
+	single_model_ops = process_model_startup("single");
+	if (!single_model_ops) goto failed;
 
 	status = dcesrv_init_context(task->event_ctx,
 				     task->lp_ctx,
@@ -72,17 +77,42 @@ static void dcesrv_task_init(struct task_server *task)
 	}
 
 	for (e=dce_ctx->endpoint_list;e;e=e->next) {
+		const struct model_ops *this_model_ops = single_model_ops;
+
 		enum dcerpc_transport_t transport =
 			dcerpc_binding_get_transport(e->ep_description);
 
+		/*
+		 * Ensure that -Msingle sets e->use_single_process for
+		 * consistency
+		 */
+
+		if (task->model_ops == single_model_ops) {
+			e->use_single_process = true;
+		}
+
 		if (transport == NCACN_HTTP) {
 			/*
 			 * We don't support ncacn_http yet
 			 */
 			continue;
+
+			/*
+			 * For the next two cases, what we are trying
+			 * to do is put the NETLOGON server into the
+			 * standard process model, not single, as it
+			 * has no shared handles and takes a very high
+			 * load.  We only do this for ncacn_np and
+			 * ncacn_ip_tcp as otherwise it is too hard as
+			 * all servers share a socket for ncalrpc and
+			 * unix.
+			 */
+		} else if (e->use_single_process == false) {
+			this_model_ops = task->model_ops;
 		}
 
-		status = dcesrv_add_ep(dce_ctx, task->lp_ctx, e, task->event_ctx, model_ops);
+		status = dcesrv_add_ep(dce_ctx, task->lp_ctx, e, task->event_ctx,
+				       this_model_ops);
 		if (!NT_STATUS_IS_OK(status)) goto failed;
 	}
 
-- 
1.9.1


From 67c6128b79c34fdf35ebfeffbdb64ff57591f43c Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Mon, 14 Nov 2016 10:11:05 +1300
Subject: [PATCH 2/6] TODO: s4-rpc_server: Do not check association groups for
 NETLOGON

If this RPC server is not going to use handles (actually a generic
flag) then do not check the assocation group provided.  This in turn
allows us to easily make NETLOGON run in multiple processes.

Signed-off-by: Andrew Bartlett <abartlet at samba.org>

TODO:  no '== false'
---
 source4/rpc_server/dcerpc_server.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c
index fed4c29..1240d6f 100644
--- a/source4/rpc_server/dcerpc_server.c
+++ b/source4/rpc_server/dcerpc_server.c
@@ -806,6 +806,33 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
 		call->conn->assoc_group = dcesrv_assoc_group_new(call->conn,
 								 call->conn->dce_ctx);
 	}
+
+	/*
+	 * The NETLOGON server does not use handles and so
+	 * there is no need to support association groups, but
+	 * we need to give back a number regardless.
+	 *
+	 * We have to do this when it is not run as a single process,
+	 * because then it can't see the other valid association
+	 * groups.  We handle this genericly for all endpoints not
+	 * running in single process mode.
+	 *
+	 * We know which endpoint we are on even before checking the
+	 * iface UUID, so for simplicity we enforce the same policy
+	 * for all interfaces on the endpoint.
+	 *
+	 * This means that where NETLOGON
+	 * shares an endpoint (such as ncalrpc or of 'lsa over
+	 * netlogon' is set) we will still check association groups.
+	 *
+	 */
+
+	if (call->conn->assoc_group == NULL &&
+	    call->conn->endpoint->use_single_process == false) {
+		call->conn->assoc_group
+			= dcesrv_assoc_group_new(call->conn,
+						 call->conn->dce_ctx);
+	}
 	if (call->conn->assoc_group == NULL) {
 		return dcesrv_bind_nak(call, 0);
 	}
-- 
1.9.1


From f23e85c1cc653346989df1b8c0c64e2e9bb3b14f Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Mon, 14 Nov 2016 10:15:39 +1300
Subject: [PATCH 3/6] TODO: selftest: Use 'rpc server port:netlogon' smb.conf
 option

We need this because once we make NETLOGON run in multiple processes,
it will need its own port, and socket_wrapper can not currently allocate
and ephemeral port.  It also tests the option, which others have asked be
made available to firewall drsuapi.

Signed-off-by: Andrew Bartlett <abartlet at samba.org>

TODO: also verify the default 'rpc server port' option
---
 selftest/target/Samba4.pm | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm
index 80fbd03..756a3d2 100755
--- a/selftest/target/Samba4.pm
+++ b/selftest/target/Samba4.pm
@@ -592,6 +592,9 @@ sub provision_raw_step1($$)
         idmap_ldb:use rfc2307=yes
 	winbind enum users = yes
 	winbind enum groups = yes
+
+        rpc server port:netlogon = 1026
+
 ";
 
 	print CONFFILE "
-- 
1.9.1


From 684b84eff1501f7d4b1f8bea358df908c4ce09fc Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Mon, 21 Nov 2016 13:31:39 +1300
Subject: [PATCH 4/6] TODO: s4-netlogon: Push the netlogon server in the AD DC
 into multiple processes

This allows the NETLOGON server to scale better, as it is often a bottleneck

What we are doing here is keeping the forced single process only for
other servers that declare they use DCE/RPC handles.

Signed-off-by: Andrew Bartlett <abartlet at samba.org>

TODO: not between

        transport =
                dcerpc_binding_get_transport(binding);
and
        if (transport == ...)

TODO: move above (or below)
---
 source4/rpc_server/dcerpc_server.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c
index 1240d6f..05c0206 100644
--- a/source4/rpc_server/dcerpc_server.c
+++ b/source4/rpc_server/dcerpc_server.c
@@ -284,6 +284,20 @@ _PUBLIC_ NTSTATUS dcesrv_interface_register(struct dcesrv_context *dce_ctx,
 
 	transport =
 		dcerpc_binding_get_transport(binding);
+
+	/*
+	 * If we are not using handles, there is no need for force
+	 * this service into using a single process.
+	 *
+	 * However, due to the way we listen for RPC packets, we can
+	 * only do this if we have a single service per pipe or TCP
+	 * port, so we still force a single combined process for
+	 * ncalrpc.
+	 */
+	if (iface->flags & DCESRV_INTERFACE_FLAGS_HANDLES_NOT_USED) {
+		use_single_process = false;
+	}
+
 	if (transport == NCACN_IP_TCP) {
 		int port;
 		char port_str[6];
-- 
1.9.1


From d0060e1a1faf86e8c4ce6bd8d0660cbf7a96c52e Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Wed, 14 Dec 2016 11:58:48 +1300
Subject: [PATCH 5/6] s4-rpc_server: Add braces to better follow coding style

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source4/rpc_server/service_rpc.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/source4/rpc_server/service_rpc.c b/source4/rpc_server/service_rpc.c
index 63418f4..8fb8332 100644
--- a/source4/rpc_server/service_rpc.c
+++ b/source4/rpc_server/service_rpc.c
@@ -113,7 +113,9 @@ static void dcesrv_task_init(struct task_server *task)
 
 		status = dcesrv_add_ep(dce_ctx, task->lp_ctx, e, task->event_ctx,
 				       this_model_ops);
-		if (!NT_STATUS_IS_OK(status)) goto failed;
+		if (!NT_STATUS_IS_OK(status)) {
+			goto failed;
+		}
 	}
 
 	irpc_add_name(task->msg_ctx, "rpc_server");
-- 
1.9.1


From 8d9da0ea60c6fe6845ecfed77a76443d5ee9b96d Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Mon, 14 Nov 2016 11:24:03 +1300
Subject: [PATCH 6/6] TODO: s4-rpc_server: Allow each interface to declare if
 it uses handles

This will allow the NETLOGON server in the AD DC to declare that it does not use
handles, and so allow some more flexibility with association groups

Signed-off-by: Andrew Bartlett <abartlet at samba.org>

TODO: needs to be moved up the patch stack, otherwise the others don't compile
(s4-netlogon: Push the netlogon server in the AD DC into multiple processes)

TODO:
It seems that the split of this commit and "s4-netlogon: Push the netlogon
server in the AD DC into multiple processes" went wrong.

The change from "s4-netlogon: Push the netlogon
server in the AD DC into multiple processes" should be squashed into
this commit.

And the changes to source4/rpc_server/netlogon/dcerpc_netlogon.c from
this commit should be in the "s4-netlogon: Push the netlogon
server in the AD DC into multiple processes" commit.
---
 pidl/lib/Parse/Pidl/Samba4/NDR/Server.pm      | 21 +++++++++++++--------
 source4/rpc_server/dcerpc_server.h            |  4 ++++
 source4/rpc_server/dcesrv_mgmt.c              | 10 ++++++++++
 source4/rpc_server/handles.c                  | 10 ++++++++++
 source4/rpc_server/netlogon/dcerpc_netlogon.c |  9 +++++++++
 source4/rpc_server/remote/dcesrv_remote.c     |  1 +
 6 files changed, 47 insertions(+), 8 deletions(-)

diff --git a/pidl/lib/Parse/Pidl/Samba4/NDR/Server.pm b/pidl/lib/Parse/Pidl/Samba4/NDR/Server.pm
index fe5ca0b..88c7705 100644
--- a/pidl/lib/Parse/Pidl/Samba4/NDR/Server.pm
+++ b/pidl/lib/Parse/Pidl/Samba4/NDR/Server.pm
@@ -193,14 +193,19 @@ static NTSTATUS $name\__op_ndr_push(struct dcesrv_call_state *dce_call, TALLOC_C
 }
 
 static const struct dcesrv_interface dcesrv\_$name\_interface = {
-	.name		= \"$name\",
-	.syntax_id  = {".print_uuid($uuid).",$if_version},
-	.bind		= $name\__op_bind,
-	.unbind		= $name\__op_unbind,
-	.ndr_pull	= $name\__op_ndr_pull,
-	.dispatch	= $name\__op_dispatch,
-	.reply		= $name\__op_reply,
-	.ndr_push	= $name\__op_ndr_push
+	.name		    = \"$name\",
+	.syntax_id          = {".print_uuid($uuid).",$if_version},
+	.bind		    = $name\__op_bind,
+	.unbind		    = $name\__op_unbind,
+	.ndr_pull	    = $name\__op_ndr_pull,
+	.dispatch	    = $name\__op_dispatch,
+	.reply		    = $name\__op_reply,
+	.ndr_push	    = $name\__op_ndr_push,
+#ifdef DCESRV_INTERFACE_$uname\_FLAGS
+	.flags              = DCESRV_INTERFACE_$uname\_FLAGS
+#else
+	.flags              = 0
+#endif
 };
 
 ";
diff --git a/source4/rpc_server/dcerpc_server.h b/source4/rpc_server/dcerpc_server.h
index 8905c5d..ecb874e 100644
--- a/source4/rpc_server/dcerpc_server.h
+++ b/source4/rpc_server/dcerpc_server.h
@@ -67,8 +67,12 @@ struct dcesrv_interface {
 
 	/* for any private use by the interface code */
 	const void *private_data;
+
+	uint64_t flags;
 };
 
+#define DCESRV_INTERFACE_FLAGS_HANDLES_NOT_USED 0x00000001
+
 enum dcesrv_call_list {
 	DCESRV_LIST_NONE,
 	DCESRV_LIST_CALL_LIST,
diff --git a/source4/rpc_server/dcesrv_mgmt.c b/source4/rpc_server/dcesrv_mgmt.c
index 577f0fb..ecb90d8 100644
--- a/source4/rpc_server/dcesrv_mgmt.c
+++ b/source4/rpc_server/dcesrv_mgmt.c
@@ -26,6 +26,16 @@
 
 #define DCESRV_INTERFACE_MGMT_BIND(call, iface) \
        dcesrv_interface_mgmt_bind(call, iface)
+/*
+ * This #define allows the mgmt interface to accept invalid
+ * association groups, because association groups are to coordinate
+ * handles, and handles are not used in mgmt. This in turn avoids
+ * the need to coordinate these across multiple possible NETLOGON
+ * processes, as an mgmt interface is added to each
+ */
+
+#define DCESRV_INTERFACE_MGMT_FLAGS DCESRV_INTERFACE_FLAGS_HANDLES_NOT_USED
+
 static NTSTATUS dcesrv_interface_mgmt_bind(struct dcesrv_call_state *dce_call,
 					     const struct dcesrv_interface *iface)
 {
diff --git a/source4/rpc_server/handles.c b/source4/rpc_server/handles.c
index 820da49..af49f4c 100644
--- a/source4/rpc_server/handles.c
+++ b/source4/rpc_server/handles.c
@@ -44,6 +44,11 @@ _PUBLIC_ struct dcesrv_handle *dcesrv_handle_new(struct dcesrv_connection_contex
 	struct dcesrv_handle *h;
 	struct dom_sid *sid;
 
+	/*
+	 * For simplicty, ensure we abort here for an interface that has no handles (programmer error)
+	 */
+	SMB_ASSERT((context->iface->flags & DCESRV_INTERFACE_FLAGS_HANDLES_NOT_USED) == 0);
+
 	sid = &context->conn->auth_state.session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
 
 	h = talloc_zero(context->conn->assoc_group, struct dcesrv_handle);
@@ -80,6 +85,11 @@ _PUBLIC_ struct dcesrv_handle *dcesrv_handle_fetch(
 	struct dcesrv_handle *h;
 	struct dom_sid *sid;
 
+	/*
+	 * For simplicty, ensure we abort here for an interface that has no handles (programmer error)
+	 */
+	SMB_ASSERT((context->iface->flags & DCESRV_INTERFACE_FLAGS_HANDLES_NOT_USED) == 0);
+
 	sid = &context->conn->auth_state.session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
 
 	if (ndr_policy_handle_empty(p)) {
diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c
index 416acdc..15f0a77 100644
--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -46,6 +46,15 @@
 #define DCESRV_INTERFACE_NETLOGON_BIND(call, iface) \
        dcesrv_interface_netlogon_bind(call, iface)
 
+/*
+ * This #define allows the netlogon interface to accept invalid
+ * association groups, because association groups are to coordinate
+ * handles, and handles are not used in NETLOGON. This in turn avoids
+ * the need to coordinate these across multiple possible NETLOGON
+ * processes
+ */
+#define DCESRV_INTERFACE_NETLOGON_FLAGS DCESRV_INTERFACE_FLAGS_HANDLES_NOT_USED
+
 static NTSTATUS dcesrv_interface_netlogon_bind(struct dcesrv_call_state *dce_call,
 					       const struct dcesrv_interface *iface)
 {
diff --git a/source4/rpc_server/remote/dcesrv_remote.c b/source4/rpc_server/remote/dcesrv_remote.c
index c6ef757..69ce08c 100644
--- a/source4/rpc_server/remote/dcesrv_remote.c
+++ b/source4/rpc_server/remote/dcesrv_remote.c
@@ -374,6 +374,7 @@ static bool remote_fill_interface(struct dcesrv_interface *iface, const struct n
 	iface->ndr_push = remote_op_ndr_push;
 
 	iface->private_data = if_tabl;
+	iface->flags = 0;
 
 	return true;
 }
-- 
1.9.1

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: OpenPGP digital signature
URL: <http://lists.samba.org/pipermail/samba-technical/attachments/20161219/97ad4432/signature.sig>


More information about the samba-technical mailing list