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