outsourcing DCE/RPC to alternate programs - runtime config option

Luke Kenneth Casson Leighton lkcl at lkcl.net
Sat Dec 11 11:40:44 GMT 2004


>  > other transports are not bound to smbd they can directly listen on
>  > the socket,
>   > but you're right for the pipe vs. interface problem
> 
>   If you directly listen on the socket, then how do you register with
>   the endpoint mapper? 

 i don't quite understand the question / context enough to be able to
 answer this, mainly because in FreeDCE it's taken care of by the
 server-side runtime code.
 
 as a server, you indicate which transports you intend to
 register to listen on, and one of the first things that the
 FreeDCE server-side runtime libraries do is to contact the endpoint
 mapper on "loopback" of all transports it has available (whatever
 loopback means in the context _of_ that transport) to check whether the
 transport the server intends to register on is free, and to obtain, if
 relevant, appropriate ports in the case of UDP and TCP (which are
 known as towers in DCE/RPC terminology.  or floors.  or something.  i
 forget which).


 i should point out, but i don't know if it's relevant,
 that of course the epmapper is not contacted by NT clients
 to resolve SMB-IPC$-authenticated-transport-namedpipes:
 the reason is because of course the nca contact string
 _contains_ all the endpoint information already (format
 "ncacn_np:\\server\pipeendpointnameegspoolss")

 the FreeDCE client-side code is passed all sorts of weird
 and wonderful ncacn strings and it's the *runtime* library's
 job to contact the endpoint mapper IF NEEDED to resolve any
 missing components (e.g. if an application passes in a uuid,
 i believe that the FreeDCE runtime client code sends out
 broadcast queries to contact any epmapper in existence).


 ... but as i said, i'm not entirely sure of the question,
 so this may or may not help - or be relevant.


> Also, how do you handle things like schannel
>   which require state being passed from one pipe to another?
 
 in TNG - and i am only giving this as an example purely for
 the purposes of demonstrating that the issue raised _can_
 be solved - user state information (such as the session keys)
 is stored in a root-only-accessible TDB database.

 what i did was to stuff the vuid_struct into a tdb database, using what
 was originally the SMB vuid (but this later became useful for other
 purposes) and the smbd process id as the lookup index into that table.

 the vuid+smbd-pid pair is somehow passed over the unix domain socket in a
 manner which i at present have forgotten about the details (!)

 i _think_ what i did was in the
 what-would-become-a-dso-loaded-"open"-function,
 which of course would have the vuid_struct passed to it by the
 server-side as one of its arguments, i do this:

 1) bundle up the vuid_struct using marshalling/pickling.
 2) store the vuid_struct in a root-only-accessible tdb,
    using the vuid+smbd-pid as a key
 3) initiate a connection down a root-only-accessible unix-domain-socket
    sending as the first couple of bytes the unique vuid+pid
 4) the recipient (spoolssd, samrd, netlogond) reads that vuid+pid,
    accesses the tdb, recreates the vuid_struct, shoves it into
	the connection state information, and carries on.


 in this rather excessively overdesigned manner, it is possible for smbd
 to pass over the user-context, which includes the schannel information
 and/or authentication information, to other programs.

 [well, actually, smbd acts as a broker for that state information:
  it's actually the client-side DCE/RPC information or even
  more specifically the client-side DCE/RPC SChannel code that
  generates that state information, and all other components just
  get to pass it around until someone actually needs it!]

 of course, a much simpler solution would be to just stuff
 the vuid_struct _itself_ over the communication mechanism
 (from smbd to the recipient server program)

 i have absolutely _no_ idea why i did it the other way:
 probably because my tiny brain thought that stuffing a rather
 large vuid_struct over a unix domain socket was inelegant,
 but it _really_ makes no odds!

 anyway: this is just demonstrating _one_ possible solution -
 there are, i am sure, plenty of other solutions that suit
 the samba 3 and samba 4 architecture much better.



 
>   For simple cases where you have a fixed port and no fancy
>   authentication options then listening on the socket will work, 


 there are two successful projects that succesfully implement
 authentication using smbd as the "outsourcer" / "broker" -
 samba tng and XAD, using in the case of samba-tng a "we always
 outsource to /usr/local/samba/var/locks/.msrpc/pipename"
 approach, and in the case of XAD, a hard-coded "if the
 pipename is samr, NETLOGON or lsass, outsource-it to
 /var/xad/private/pipename, otherwise let smbd deal with it"
 approach.

 also i should point out that using a socket is not an exclusive
 solution: there's always shared memory as a viable option, and 
 i am sure that people will think of other viable methods.
 
 [ux-dscks was just the most convenient one for me to implement and
 restrict to root-only-accessible, and yes i have since found
 some code that implements a sockets interface, read, write,
 open, close, over shared memory!  the code was written by
 sun *shudder* and it really _did_ replace read, write, open,
 close, via the same LD_LIBRARY_PATH preloading trick that
 andrew did for smbsh ]

> but I
>   think that if we are going to offer a set of external hooks that we
>   should allow them to be fully functional.

 yes.

>   This also allows the external code not to worry about signing and
>   sealing. The forwarding code in the samba rpc server would remove the
>   signing and sealing and pass the naked packets to the unix domain
>   socket. So a client could negotiate signed/sealed RPC without every
>   external rpc implementation having to worry about implementing those.
>   This is especially important given the interactions between the
>   signing/sealing code and the base SMB authentication code (which must
>   be done inside smbd for obvious reasons).

 in 2001, i successfully integrated the samba TNG authentication
 system into FreeDCE, and started integrating the NTLMSSPv1
 signing / sealing code into FreeDCE - using Samba TNG's
 unix-domain-socket mechanism to simply pass over unmodified
 DCE/RPC traffic and of course the "initial" vuid context
 (as described in somewhat from-4-years-ago-memory-fuzzy
 detail above).

 also, luke howard has done likewise in his XAD commercial
 project, following a similar course.

 so it _can_ be done, and _has_ been done, and very easily,
 because the FreeDCE code understands the concept of signing and
 sealing (and takes care of it for you), and simply requires
 that you plug in about 25 functions into one of the APIs
 (can be done as a dso, thanks to wez), add in an extra
 contstant into the FreeDCE header files to recognise your
 wizzy-dizzy-security-mechanism (in this case NTLMSSP which
 is 0xa IIRC), and you're done.
 
 took me about two to three weeks to do, IIRC.

 so if you restrict the design of the outsourcing API at the
 top level, it will, in my opinion - i am really sorry to have
 to say this - make the outsourcing API not worth implementing.


 that having been said: should you so wish, you could implement
 a special DSO for samba 3 / samba 4 which implements, for the
 specific purposes and reasons you describe, exactly what you
 believe is required for samba 3 / samba 4.

 of course, then, should other projects choose to also not
 implement or not use DCE/RPC security brokering in _their_
 projects, they will be able to follow your example.

 l.



More information about the samba-technical mailing list