Trying to understand epmapper registration

Andrew Bartlett abartlet at samba.org
Sat Mar 3 14:27:49 MST 2012


On Sat, 2012-03-03 at 12:38 +0100, Andreas Schneider wrote:
> On Saturday 03 March 2012 21:44:55 Andrew Bartlett wrote:
> > > Do you mean the table with the GUID, endpoint names, and on which
> > > endpoints it should be available? I don't really get what you're talking
> > > about and what the problem is :)
> > 
> > I'm sorry, clearly I have not been specific enough.  To continue using
> > dssetup as my example, here is the relevant fucntion in master:
> > 
> > static bool rpc_setup_dssetup(struct tevent_context *ev_ctx,
> > 			      struct messaging_context *msg_ctx,
> > 			      const struct dcerpc_binding_vector *v)
> > {
> > 	const struct ndr_interface_table *t = &ndr_table_dssetup;
> > 	const char *pipe_name = "dssetup";
> > 	struct dcerpc_binding_vector *v2;
> > 	enum rpc_service_mode_e epm_mode = rpc_epmapper_mode();
> > 	NTSTATUS status;
> > 	bool ok;
> > 
> > 	status = rpc_dssetup_init(NULL);
> > 	if (!NT_STATUS_IS_OK(status)) {
> > 		return false;
> > 	}
> > 
> > 	if (epm_mode != RPC_SERVICE_MODE_DISABLED) {
> > 		v2 = dcerpc_binding_vector_dup(talloc_tos(), v);
> > 		if (v2 == NULL) {
> > 			return false;
> > 		}
> > 
> > 		status = dcerpc_binding_vector_replace_iface(t, v2);
> > 		if (!NT_STATUS_IS_OK(status)) {
> > 			return false;
> > 		}
> > 
> > 		status = dcerpc_binding_vector_add_np_default(t, v2);
> > 		if (!NT_STATUS_IS_OK(status)) {
> > 			return false;
> > 		}
> > 
> > 		ok = setup_dcerpc_ncalrpc_socket(ev_ctx,
> > 						 msg_ctx,
> > 						 pipe_name,
> > 						 NULL);
> > 		if (!ok) {
> > 			return false;
> > 		}
> > 
> > 		status = dcerpc_binding_vector_add_unix(t, v2, pipe_name);
> > 		if (!NT_STATUS_IS_OK(status)) {
> > 			return false;
> > 		}
> > 
> > 		status = rpc_ep_register(ev_ctx,
> > 					 msg_ctx,
> > 					 t,
> > 					 v2);
> > 		if (!NT_STATUS_IS_OK(status)) {
> > 			return false;
> > 		}
> > 	}
> > 
> > 	return true;
> > }
> > 
> > The function does:
> >  - copies in the TCP/IP port bindings
> 
> Only if it is enabled and this is normally not the case cause smbd can't 
> handle rpc tcpip connection. This is why we developed the prefork stuff and 
> have lsasd.
> 
> This is normally and emtpy structure.
> 
> >  - registers ncacn_np pipes based on the IDL interface table
> >  - registers the ncaclrpc pipe
> > 
> > My question is:  Is there a reason why this is not entirely table
> > driven, based on this IDL interface table:
> 
> No, I think there is no reason.
> 
> > 
> > [
> > 	uuid("3919286a-b10c-11d0-9ba8-00c04fd92ef5"),
> > 	version(0.0),
> > 	endpoint("ncacn_np:[\\pipe\\lsarpc]", "ncacn_np:[\\pipe\\lsass]",
> > "ncacn_ip_tcp:", "ncalrpc:"),
> > 	pointer_default(unique),
> > 	helpstring("Active Directory Setup")
> > ] interface dssetup
> > 
> > (this is used by dcerpc_binding_vector_add_np_default already).
> > 
> > I'm not trying to poke blame or suggest that hard-coding it was not the
> > most expedient option available at the time.  I'm just trying to
> > understand the why behind the code we have so far, as it seems I will be
> > needing to undertake some significant works in this area.  It helps to
> > understand not just the actions, but the intentions of those who have
> > been before me.  Naturally, I'll also keep you in the loop as I do the
> > work.
> 
> It made it easier to do it somehow manually than relying on the IDL table for 
> the service. For RPC over TCPIP we only open one port. Copying it and 
> replacing the GUID was the easiest way to implement it. If you want to always 
> rely on the idl then you can do that, but then you always have to pass all 
> options like ip address and ports to the functions even if you don't need it. 
> 
> As it is now it was the simplest way to pass around a structure with all ip 
> address and port combination we can have.
> 
> I someone specifies ip addresses to listen on you need to open a random port 
> on all of them and register each service for all of them on the endpoint 
> mapper. So it was the easiest to setup the endpoint mapper structure and pass 
> it down and only replace the GUID. I didn't want to introduce yet another 
> structure to pass around the information.
> 
> Maybe we should create more abstract functions for registering and have a 
> public library which can be used by openchange to register their endpoints.
> 
> > > We need(ed) to call rpc_spoolss_init() or if you connect over a named pipe
> > > to smbd, then smbd will tell the client that it doesn't know the rpc
> > > protocol and drop the connection. This registration is (was) needed to
> > > accept the connection and forward it over the named pipe proxy to the
> > > correct service, spoolssd.
> > > 
> > > Maybe this has changed and isn't needed anymore. It was needed by the time
> > > I was doing the work. I think we need to try it and maybe make sure it
> > > isn't requried anymore.
> > 
> > I'll do that.  We should be able to put our RPC services into one of two
> > categories:  Services that are embedded in the forked smbd SMB child
> > process, and external services (the rest).  We should not need to
> > register external services except to the epmapper, and just fail
> > gracefully if we cannot find the socket.
> 
> I agree. Maybe it is already working in the meantime. We just need to move the 
> rpc_<service>_init() calls into the embedded case.

> > > > Given the support for automatically removing registrations when
> > > > processes shut down, I imagined it would need to be registred from the
> > > > same process.
> > > 
> > > Do you talk about registered endpoints in smbd or rpc_<rpc>_init() now?
> > 
> > I'm sorry, I was confused by the rpc_setup_lsarpc() call, being called
> > from main() -> dcesrv_ep_setup -> rpc_setup_lsarpc().  However, it is
> > guarded and the registration only applies in embedded mode.
> > 
> > The rpc_lsarpc_init() function appears to be called from both that and
> > setup_lsasd().  I don't know if that matters.
> 
> As you explained above it should only be called in smbd if it is embedded. The 
> rpc_lsarpc_init() call was required to get the proxy connection to the 
> external daemon working.

In which case, is my second patch from my initial mail
(0002-s3-rpc_server-Do-not-register-external-rpc-servers.patch) correct?

> > > We should differentiate between registering the process on epmd or make
> > > smbd aware of handling the connection for dssetup and forwarding it. If
> > > you mean the letter than we need to make sure that this will work.
> > 
> > If possible, I would like to make 'smbd' essentially unaware of external
> > rpc pipes, just working on what sockets exist in the ncaclrpc/np
> > directory.  Then epmd (wherever it is implemented) can deal with
> > registrations.
> 
> I would like to have epmd in its own deamon and be started like smbd from 
> s3fs. This was it could be used by s4 and s3/lsasd. I'm also fine if we create 
> a library and fork it from s3/s4.

Thanks.  I'll let you know what I'm proposing once I have a working
prototype. 

Andrew Bartlett

-- 
Andrew Bartlett                                http://samba.org/~abartlet/
Authentication Developer, Samba Team           http://samba.org




More information about the samba-technical mailing list