rpcrt4: Check for null endpoint in RpcServerUseProtseqEpExW

Luke Kenneth Casson Leighton lkcl at lkcl.net
Sun Feb 22 06:23:55 CST 2009


come on folks, pick up the ball.  acknowledge that you're aware that
there is an authoritative source of information on this
horrendously-complex topic, in the form of nothing less than a fully
functioning reference implementation.

so this:

> > Ok, I'll try to find out.
> > Rob, could you suggest a good documentation source on RPC? I'm not
> > experienced in it.

>Sure, although this particular aspect isn't well documented.

simply isn't true.

it's _authoritatively_ documented, so concretely documented you could
break it into a million pieces to sink a million people who walked
into your turf, if you were in da mafia or summink :)

so - carrying on from where i hinted at you should investigate, the
"real" work is done here:

    /*
     * Call the protocol service to do the real work of creating the
     * socket(s), setting them up right, and adding them (via calls
     * to rpc__network_add_desc).
     */
    (*net_epv->network_use_protseq)
                        (pseq_id, max_calls, rpc_addr, endpoint, status);

so where is that function?  well, it's not _a_ function, because
net_epv is a pointer to a vector table [array of
higher-order-functions].  so the design of freedce is _incredibly_
well done, and allows for new transports to be dropped in at will.
and new authentication schemes.  etc.

so, where is _an_ example of a function that's pointed to by
network_use_protseq?

a quick grep through the code turns up this:

    ncklib/transport/cn/cninit.c:    rpc__cn_network_use_protseq,

having a quick look at that file actually shows _two_ connection-based
(cn) protseqs - one is tcp and the other is named pipes (which i'd
added in 2005).  both of those are in cninit.c


to answer the specific question about allocation (NULL or not NULL)
you have to chunder through quite a bit of convoluted lookups to find
out where _this_ goes to:

 (*naf_epv->naf_addr_alloc) (

 _yes_ as you can see, NULL is an acceptable endpoint parameter and
rob is correct in that it means "please allocate me aaabsolutely
aanything you like, per transport".

you can tell this from what happens inside the code.  in TCP/IP terms,
NULL means "give me an socket on 0.0.0.0 with _any_ port number".
same in UDP terms.  in ncacn_np terms, i don't honestly know - you'll
have to do some experiments to check - but you have two choices:

1) error
2) a random pipe name e.g. \pipe\0x00000NNN.0x0000NNNN

grep naf_addr_alloc shows one file - ncklib/include/comnaf.h which
shows promise, showing you what you want, but the  trail goes dead
there, until you actually _look_ at comnaf.h and you can see these:

/*
 * Declarations of the Network Address Family Extension Service init
 * routines.
 */
PRIVATE void rpc__unix_init _DCE_PROTOTYPE_ ((
        rpc_naf_epv_p_t              * /*naf_epv*/ ,
        unsigned32                   * /*status*/
    ));

PRIVATE void rpc__ip_init _DCE_PROTOTYPE_ ((
        rpc_naf_epv_p_t              * /*naf_epv*/ ,
        unsigned32                   * /*status*/
    ));

PRIVATE void rpc__dnet_init _DCE_PROTOTYPE_ ((
        rpc_naf_epv_p_t              * /*naf_epv*/ ,
        unsigned32                   * /*status*/
    ));

PRIVATE void rpc__osi_init _DCE_PROTOTYPE_ ((
        rpc_naf_epv_p_t              * /*naf_epv*/ ,
        unsigned32                   * /*status*/
    ));

which are for unix domain sockets (which i think i added as an extra
NAF in 2004), TCP/IP and UDP/IP, DecNet and goodness knows what OSI is
i _so_ don't want to know :)

_again_ it's hard to track down rpc__ip_init() and friends but jumping
straight to ls ncklib/naf/*.c (because duh the header file
ncklib/include/comnaf.h is the clue) you can see e.g. ipnaf.c

hooraaay, there's the vector table, rpc_naf_epv_t, with the static
function addr_alloc as the first member, so in the  IP cases, TCP/IP
and UDP/IP, addr_alloc in ipnaf.c is what's called by that
(*naf_epv->naf_addr_alloc) () call.

addr_alloc calls addr_set_endpoint.  addr_set_endpoint does this:

    if (endpoint == NULL || strlen ((char *) endpoint) == 0)
    {
        ip_addr->sa.sin_port = 0;
        *status = rpc_s_ok;
        return;
    }

so - hooray!  you now _authoritatively_ have your answer, thanks to
the reference implementation.

when NULL is used as the endpoint, you're expected to be given _any_
available address (which in IP terms means "any port").

now you have to do the same thing for ncacn_np. a random and globally
unique pipe name will be required.

remember also do do exactly what the reference implementation says,
when the endpoint _isn't_ NULL, and strip off leading slashes.

l.

On Sat, Feb 7, 2009 at 4:09 PM, Luke Kenneth Casson Leighton
<lkcl at lkcl.net> wrote:
> see implementation in dual BSD-licensed _and_ LGPL-licensed freedce
> reference implementation, on which MSRPC was originally blatantly
> copied (thanks to the BSD license on the 1.0 reference
> implementation).
>
> e.g. online annotated copy here:
> http://www.sfr-fresh.com/linux/misc/freedce-1.1.0.7.tar.gz:a/freedce-1.1.0.7/ncklib/com/comnet.c
>
> line 2470.
>
> anyone who is doing wine dce/rpc development _really_ needs to be
> looking at the reference implementation, side-by-side, line-for-line,
> in virtually every aspect except for exception handling, threading,
> binary-interoperability with the typelibraries and a few other areas.
>
> l.
>



More information about the wine-devel mailing list