[samba-tng] msrpc status

Luke Kenneth Casson Leighton lkcl at samba.org
Thu Dec 16 02:35:28 GMT 1999


tasks completed so far:

1) creation and implementation (first) of msrpc daemon architecture.

this has smbd construct msrpc PDUs which are fed through a unix socket
over to msrpc daemons.  each msrpc daemon listens on the unix socket for
connections (which are triggered by an SMB open) and forks() to accept the
incoming connection, just like smbd does and for exactly the same reasons
that smbd does (security, reliability, simplicity etc).

there are variations on this:

a) don't fork, have a socket array.  on each incoming packet, you will
need to do a become_user() for security reasons before processing the
function call.  you don't want anonymous users to either run as the
previous arbitrary user or as root.

this implementation variation is being considered as some of the msrpc
daemons may require to share info, or to maintain info that needs to be
around longer than the duration of an incoming connection
(\PIPE\NETLOGON).

it will be added to the type of daemons that can be created rather than
replace existing one(s).

b) have only one msrpc daemon.  fork() or socket-array, doesn't matter:
you only have one msrpc daemon.  this one daemon processes all msrpc
pipes.

c) variation on b) - allow one msrpc daemon to deal with multiple msrpc
pipes, but allow other msrpc daemons to run as well that deal with _other_
pipes.

i like this one because some of the pipes only currently support one msrpc
call, and it's a bit of a waste to have a 370k binary doing one thing!!!
(NetWkstaGetInfo on \PIPE\wkssvc).

d) remove all msrpc processing from smbd.  this requires a mini-API to be
created.  split instead of at the smb/msrpc pdu point, just feed
any-data-identified-as-msrpc-related out of smbd to, say, a unix socket.

on an SMB open - send a mini-API command to open the requested MSRPC pipe.

on an SMBtrans request, SMBreadX, send a mini-API command plus the SMB
data out of smbd's hands.

on am SMBtrans response, SMBwriteX, send a mini-API command to read the
data from the other side of the smbd/msrpc interface, then create the SMB
response.

on an SMB close, send a mini-API commannd to close the requested MSRPC
pipe.

the current implementation does a little bit of additional house-keeping,
but other than that it _has_ an implementation of this "API" - an in-house
one:

SMB open - fd = open("/tmp/.msrpc/PIPE_NAME");

SMBtrans request, SMBreadX - write(fd, smb_data, smb_len);

SMBtrans response, SMBwriteX - read(fd, smb_data, smb_len);

SNB close - close(fd)

it's not quite like that, but close enough :-)

e) allow smbd to be able to run msprc pipes in the same process. actually,
code to do this already exists.  i haven't removed this code.  i used it
to transition to independent msrpc daemons.


2) msrpc loop-back interface, aka "ncalrpc" in dce/rpc terminology.

this uses the msrpc / smb split point to jump in and bypass the smbd /
clientgen.c over SMB over TCP 127.0.0.1.  it bypasses SMB authentication
mechanisms and uses the internal msrpc authentication mechanism i had to
add.  security is implemented by only allowing programs run as root to
access the unix sockets (/tmp/.msrpc/PIPE_name - you chmod the permissions
on the .msrpc directory to 0700).

i have a little more thinking to do about this: do we want instead to
allow anyone in any user context to be able to run msrpc daemons?  if so,
we have to go for a three-level directory structure on the unix sockets:

/tmp/.msrpc 0777
/tmp/.msrpc/PIPE_name 0770 (or any other permissions)
/tmp/.msrpc/PIPE_name/socket 1777 - this is the actual unix socket.

current design:
/tmp/.msrpc 0700
/tmp/.msrpc/PIPE_name 1777 - this is the actual unix socket.

back to the loop-back interface.

if you call lsa_open_policy("\\.", ...) or lsa_open_policy("\\myserver,
...) then instead of issuing an SMB connection, the underlying code
connets straight to the unix socket for /tmp/.msrpc/lsarpc.

i have socurity stuff to deal with that may require me to use the
msrpc-agent code i wrote last week.  hmm... more thought required.

3) rpc client smb / msrpc split (more transports, client-side)

as part of the loop-back rewrite, i had to split out the code in the msrpc
client side to do either smb or loop-back, and i did it in such a way that
other transports (e.g TCP) can be added later on.

it took less time than i expected, but it wass still a pain.


4) lsarpcd lookup names and sids rewrite

lsarpcd now no longer access the smb password API database.  it uses
samr_lookup_rids and samr_lookup_names to query the SAM database (using
the new msrpc client loop-back code!) and uses lsa_lookup_sids() and
lsa_lookup_names (against using msrpc client code but this time onthe SMB
transport) to recursively loop up any names not in the same domain.

and if you think this is horrible, complain to microsoft about the the
risks of recursion, not to me: it's exactly what NT does :-)

i was slightly concerned about this behaviour:

nt client does lsalookupnames.
client connects to smbd.  smbd forks.
smbd feeds to lsarpcd.  lsarpcd forks.
lsarpcd finds that name is in its domain.
lsarpcd does a samrlookupnames over an SMB connection.
lsarpcd-as-client connects to smbd.  smbd fors.
smbd feeds to samrd.  samrd forks.
samrd process samrlookupnames request.  feeds response to smbd.
smbd feeds response over SMB connection back to lsarpcd.
lsarpcd drops SMB connection.
lsarpcd creates lsalookupnames response from samrlookupnames response.
lsarpcd feeds reponse to smbd.
smbd feeds response over SMB connection back to nt client.
nt client drops connection.

this is UGLY as sin.  it is why i created the loop-back code:

nt client does lsalookupnames.
client connects to smbd.  smbd forks.
smbd feeds to lsarpcd.  lsarpcd forks.
lsarpcd finds that name is in its domain.
lsarpcd does a samrlookupnames over a loop-back to samrd. samrd forks
samrd process samrlookupnames request.  feeds response to lsarpdc.
lsarpcd drops loopback connection.
lsarpcd creates lsalookupnames response from samrlookupnames response.
lsarpcd feeds reponse to smbd.
smbd feeds response over SMB connection back to nt client.
nt client drops connection.

this reduces the process count, somewhat.

if you really want to reduce the process count, you put lsarpcd and samrd
back into smbd.  for now, i'm prepared to run with these separate daemons
for a while, and see what happens.


5) msrpc redirector agent.

like smb-agent, this manages smb connections.  it records the credentials
of incoming connections, and allows for "reuse" of connections between
clients and servers.  this can be used to reduce the number of connections
(and therefore the number of processes) to one per set of user
credentials.

it's got potential.

it means that the msrpc daemon architecture will need to be able to accept
more that one BIND/BIND-ACK + request/response + request/response +
request/response .... drop connection sequence simultaneously.

i _think_ this is going to be a problem, making it impossible to do this
"msrpc redirecter" thing.

the difference between smb and msrpc is that smb has the ability to accept
and, most importantly, _distinguish_, multiple users on the same session
(or connection), whereas MSRPC does not.  it's already been decided in the
design of MSRPC that when you accept an MSRPC connection, you're not going
to accept multiple users on that same connection: it's a per-session
connection, that's it, folks.

hmmm....


TODO

1) fix the security holes around the loop-back msrpc code.  this may
involve using SMB authentication in the Bind / Bind Ack stage - code that
already exists but hasn't been used for this purpose.

2) examine adding a TCP interface on to the msrpc code, client and server.
this probably by implementing the DCE/RPC endport mapper.

3) implement a DCE/RPC endport mapper, client and server . add
\PIPE\epmapper.

4) debug "multiple PDU" responses, which have not been tested yet.

5) add "multiple PDU" requests, which up until \PIPE\spoolss were never
needed, client or server-side, and the msrpc code's been around for over
two years!  i can then implement an rpcclient job queye management command
that i've been meaning to do for a while.

6) verify that the MSRPC NTLMSSP authentication still works
(SamrChangeUserPassword is a good one to use).  it uses the 3WAY Auth PDU,
so there may be some issues.

7) change the MSRPC split point code to use MSRPC headers to read the
correct length of data outstanding on the socket instead of a fudge-job
right now which uses NetBIOS-session-style code [which writes out the
length of the data in a 4-byte-header then writes that much data after it]


TODO on samba itself

1) associate unix and nt user credentials in struct vuser_struct.
currently, only the unix name is stored (plus uid,gid, gid*).  this is
very messily and confusingly assumed, at unknown points in the code, to be
an NT name instead of a unix name.  or, worse, an NT name is written into
the unix name in the vuser_struct.

at present, we are lacking the ability to allow trusted domain
controller's users access to same, or worse, flattening the name space to
confuse NT users with the same NT name in different domains onto the same
unix name: a security risk in all current, existing samba releases.

2) remove all direct references to the NT-style SMB/SAM password API and
use \PIPE\NETLOGON for user validation and \PIPE\samr or \PIPE\lsarpc for
user profile information as required.

if you think this will be horrible, remember that if the authentication or
user profile grabbing is to be to the PDC and you _are_ the PDC, it will
go over MSRPC-loopback. if the authentication of user profile grabbing to
to be to a trusted DC or to the PDC and you are _not_ the PDC, it will go
over MSRPC-SMB connection.

and you _don't_ have to make that decision at the time that you use the
SamrQueryUserInfo() call or NetrSamLogon or LsaLookupSids() call, it's
done _for_ you inside the MSRPC code.

it makes for simpler code.

if (is_pdc())
{
	become_root()
	smb_pass = getpwnam(nt_user_name);
	unbecome_root()
}
else
{
	SamrQueryUserInfo(nt_user_name);
}

just becomes this:

SamrQueryUserInfo(nt_user_name);

3) rewrite or replace smbpasswd with code in rpcclient.  everything that
smbpasswd currently does: do it with rpcclient, instead.  maybe keep
smbpasswd around for backwards-compatibility or in case you want to manage
smbpasswd files off-line whilst smbd and samrd are not running.

in which case, remove all "remote" smbpasswd functionality.  or keep it
around, again, for backwards-compatibility reasons.


i think that covers most major things.  there are a few left out, such as
what is nmb-agent for.  documenting how to do inter-domain trust
relationships and how to set samba up as a BDC.

luke



More information about the samba-ntdom mailing list