Named Pipes

Rob Shearman said:

It appears the main obstacle is the license: Samba is GPL and Wine is LGPL.

Using a plugin architecture, where the plugin's header files and source code are released under the LGPL, the issue of license incompatibility can be solved with very little code. The reason is simple: the interface (ConnectNamedPipe etc.) is only a few functions, and is transferring data that will be, in the case of ncacn_np, marshalled and unmarshalled using MSRPC, and so has absolutely no relation to the means by which the data is transferred (the NamedPipe interface itself).

Even the authentication mechanism can be encapsulated using NDR into binary blobs that can be written up using IDL files. The critical information that needs to be transferred can be encapsulated in a NET_USER_INFO_3 structure, the definition of which is already available as an IDL file under a license that is compatible with both projects. The use of NET_USER_INFO_3 (or SAMR_USER_INFO_21) takes care of the majority of the authentication information required, and both Wine and Samba have compatible MIDL compilers (WIDL and pidl).

Also vital to the success of the interoperability is the inclusion of SetNamedPipeHandleState and GetNamedPipeHandleState, and the inclusion of Named Pipe message-mode flags in the implementation of the ConnectNamedPipe-or-equivalently-named function. The reason is simple: not all applications that run on Wine platforms will set "message mode" on Named Pipes. Samba's smbd, and the NamedPipes communication mechanism, will act as a third party go-between, unaffected and totally disinterested in the actual content of the traffic, and it is merely sheer coincidence that some of the targets for the NamedPipe traffic will _happen_ to be Samba 3, Samba 4 or Wine MSRPC ncacn_np services, running on the same box. But, to exclude applications that do not use or require the "message mode" capabilities purely due to an oversight in the design of a simple interface would be seen to be somewhat... foolish.

Also, regarding registration with the EndPointMapper: once NamedPipes interoperability has been achieved, it is a near-trivial matter to choose either Samba 4's epmapper service or Wine's epmapper service, and for all services (either those in Wine or those in Samba 3 or Samba 4 MSRPC services) to utilise standard epmapper registration functions, which are MSRPC-based, to register with the chosen service. of course, that assumes that Wine, Samba 3 and Samba 4 all have successful standards-compliant implementation and use of the epmapper DCE/RPC protocol, as defined in The Open Group's specification. but, regardless, it's an easy issue to solve. The key - the absolute vital strategic key - is getting the NamedPipes interoperability working. The rest is easy.

Special attention to ImpersonateNamedPipeClient

Care must be taken in the implementation of ImpersonateNamedPipeClient when proxying MSRPC over an NamedPipes emulation layer into and through samba. The way that the authentication works is that the security context starts off as "anonymous" at the NetBIOS level, then potentially goes to "authenticated" at the SMB session level, which is then inherited by the IPC$ share, and it's this authentication context that must be "communicated" across the NamedPipes emulation layer at startup time.

but wait... it gets better! Once an MSRPC connection is made over that (authenticated) NamedPipes emulation layer, and you've gone to all the trouble to do so, the MSRPC layer itself may perform authentication, throwing away - or better "over-riding" - the security context just obtained.

That's not all: as you're aware, DCE/RPC has a mechanism where threads can perform their own DCE/RPC calls simultaneously, and the DCE/RPC infrastructure is responsible for multiplexing and de-multiplexing the traffic. In other words, when a client application starts a new thread, there's an "assoc_id" field that is incremented, to uniquely identify the thread, and the simplest implementation at the server end is to fire up a separate thread, so as to preserve the application semantics and provide expected "thread-like" behaviour (Samba's MSRPC design does not do this, as threads is not considered to be "the unix way", and this will continue to cause unexpected and unexplainable issues until such time as they either use threads or provide exceptionally complex emulation infrastructure to provide thread-like semantics. Bottom line: ditch as many of the samba MSRPC services as you possibly can, to avoid problems).

The reason for mentioning the multiplexing is this: each thread can have its own security context!!

multi-threading client behaviour was first observed in spoolss MSRPC traffic, in 1999. a "Change Notify" thread was fired up by the client, and a different assoc id allocated by NT's MSRPC server infrastructure. whilst the initial spoolss connection was carried out over an anonymous IPC$ connection, the "Change Notify" function required authentication, and so the second client thread required to perform MSRPC authentication.... over an existing MSRPC session!

The design of the NamedPipes emulation layer _may_ need to take this into account. actually, it will almost certainly need to take it into account. And the Samba "Franky" design will almost undoubtedly have multiple security contexts associated with a connection, and now you know why.

Mention of RpcImpersonateClient and ImpersonateNamedPipeClient back in 2005! - a reference to a post a long while back, outlining how wine could transparently and seamlessly implement security contexts, with the "named pipe emulation" layer taking care of everything, underneath.

"Pre-Authenticated PDU extension"

from :

"In particular, the solution to "inheriting" security contexts over NamedPipes is described, by extending MSRPC to include a new PDU packet type. "Pre-Authentication" of a sorts, if you will, which of course can only be carried out over cast-iron-securable transports (such as root-only-accessible unix domain sockets).

By extending MSRPC in this way, it's possible for projects that use and implement DCE/RPC to interoperate in a "clean" manner, without having to worry about Free Software License incompatibilies. Any project that has an MSRPC-compatible IDL compiler can use the IDL file, containing the security context, as the specification.

No actual code need be exchanged or cross-licensed."


a specification was written nearly a decade ago for unix-based services to be able to interoperate using NTLM authentication over MSRPC. This may prove useful as an "entry-point", to get that initial authentication context. The alternative is to mandate the use of Winbind, and for the NamedPipes system to integrate with that. Winbind is a bit of a heavy-weight in its setup requirements, and may be extremely off-putting for some Wine users, if forced onto them as a requirement. The PAULAD specification, which is implemented as an MSRPC service, is the "middle-man" choice.

SetNamedPipeHandleState and WaitNamedPipeHandleState in smbd/ipc.c

in samba 3, the necessary functions are stubs. in tng, they at least hand over the incoming parameters to a pipes_struct. both tng and samba 3 however haven't got a daaaamn clue as to what to do next :) it's _definitely_ the case that on a Win32 port of samba the SetNamedPipeHandleState etc. functions should be called; in the case of the "proxy" system however it's clear that _all_ of these functions - pipe open, pipe read, pipe write, transact, setnphs, wnphs, should all be "outsourced" to a dynamic loadable module.

in the case of samba 3, samba 3 can be happy to not bother to set named pipe handle state etc. as its communication with samba 4 is exclusively named pipe message-mode-based.

in the case of wine, the .so will need to do a hell of a lot more.

and, for a win32 port, a _new_ .so (or dll in that case) could call direct win32 functions.

everybody's happy. hurrah.

<pre> /****************************************************************************


static BOOL api_WNPHS(char *inbuf, char *outbuf, pipes_struct *p, char *param, int param_len) {

  • uint16 priority;

    if (!param || param_len < 2)

    • return False;
    priority = SVAL(param, 0);

    DEBUG(4, ("WaitNamedPipeHandleState priority %x\n", priority)); if (wait_rpc_pipe_hnd_state(p, priority)) {

    • /* now send the reply */ send_trans_reply(inbuf, outbuf, NULL, NULL, NULL, 0, param_len,
      • False);
      return True;
    } return False;




static BOOL api_SNPHS(char *inbuf, char *outbuf, pipes_struct *p, char *param, int param_len) {

  • uint16 id;

    if (!param || param_len < 2)

    • return False;
    id = SVAL(param, 0);

    DEBUG(4, ("SetNamedPipeHandleState to code %x\n", id)); if (set_rpc_pipe_hnd_state(p, id)) {

    • /* now send the reply */ send_trans_reply(inbuf, outbuf, NULL, NULL, NULL, 0, param_len,
      • False);
      return True;
    } return False;

} </pre>

Named Pipe Interoperability RFC

this specification is intended to be implemented as a library, similar to a systems library that provides for example TCP/IP in userspace. thus it could easily be utilised by samba, samba tng, samba 4, apache runtime or in fact any POSIX-compliant system that intends to offer interoperable "Windows NT Named Pipe Emulation".

the purpose of the document is to provide a guide to creating emulated implementation of Windows NT Named Pipes. implementors could use this to communicate between clients and servers inside their applications (such as the Wine application), with the added benefit that additional applications (such as the Samba application) that also conformed to the specification could interoperate. For example, the creation of a NamedPipe inside a Samba service could be talked to by a Wine client, and vice-versa.

ultimately the specification _could_ potentially be used as a guide to writing a kernel-level implementation of Windows NT Named Pipes emulation.

Note that this specification does NOT include "transfer of data over a network", as that task is carried out by SMB clients and SMB servers utilising SMBopenX, SMBclose, SMBreadX, SMBwriteX and SMBtrans2 subcommands 0x1, 0x26 and 0x53 to represent SetNPHS, WaitNamedPipe and TransactNamedPipe.

Note that this specification does NOT have the API of the Win32 functions it is intended to emulate but is instead based very much on the design of the SMB protocols (much simplified), and thus provides an exact topological mapping of all SMB operations necessary to provide full Named Pipes functionality.

Missing from the specification (but mandatory) at this time is PeekNamedPipe and GetNamedPipeHandleState, because it is clear that the functionality inside of Samba is entirely missing support for such (see call_trans2qpipeinfo in samba 3 smbd/trans2.c source code). Research WILL be required at a later stage in the form of running Win32 test applications, along with examination of the resultant network traffic, in order to determine the necessary support inside Samba for these two vital Named Pipe operations. From the design of Wine, and the stub code in smbd/trans2.c it is likely that these two functions will simply be direct mappings from NtQueryFileInformation #defines onto Trans2_QueryFileInfo, with blindingly obvious parameters and data structures to anyone familiar with both dlls/ntdll/file.c in Wine, and smbd/trans2.c in Samba.


comments here


NamedPipes (last edited 2012-07-25 18:16:21 by KyleAuble)