dce/rpc "client" api
Luke Kenneth Casson Leighton
lkcl at samba.org
Fri Aug 18 02:20:09 GMT 2000
On Thu, 17 Aug 2000, Jeremy Allison wrote:
> On Thu, Aug 17, 2000 at 03:40:25PM +1000, Luke Kenneth Casson Leighton wrote:
> > i'm adding the following api into cli_connect.c, it's basically replacing
> > all the switch statements with a function table. it will make it easier
> > to add DCE/RPC over TCP.
>
> Luke, after all our recent discussions this is the wrong way to
> propose a change to HEAD (if, that is, you're proposing a change to
> HEAD). "I'm adding" - ie. the implication being there's
> no discussion over it, is not the correct phrasing to use here.
ok, then i rephrase: i am proposing the following api in cli_connect.c.
if anyone can think of any improvements, suggestions, caveats, please do
so [i notice some below - thx jeremy].
> > also, The Plan Is, to make these function tables dynamically loadable.
> > cli_ncacn_np.so, for example, to handle DCE/RPC over SMB. cli_ncalrpc.so
> > to handle DCE/RPC over loop-back (currently implemented as unix domain
> > sockets, only accessible by/as root).
>
> Again, we're not yet ready to add .so support into HEAD until
> we determine how this should work across all supported OS'es.
ok, thanks for letting me know, i shan't .so-itise them, then.
> > typedef struct cli_connect_fns
> > {
> > /* create new connection. strictly speaking, one arg should be
> > * full dce/rpc format: e.g "ncacn_np:\\server\pipe\pipename" */
> > void *cli_connect_add(const char *pipe_name,
> > const vuser_key *key,
> > const char *srv_name,
> > const struct ntuser_creds *ntc,
> > BOOL reuse, BOOL *is_new_connection);
> >
> > /* terminate client connection */
> > void cli_connection_free(void *con);
> >
> > /* get nt creds associated with an msrpc session. */
> > struct ntdom_info *cli_conn_get_ntinfo(void *con);
> >
> > /* get a server name associated with a connection */
> > BOOL cli_con_get_srvname(void *con, char *srv_name);
> >
> > /* write to a pipe */
> > BOOL rpc_api_write(void *con, prs_struct *data);
> >
> > /* read from a pipe */
> > BOOL rpc_api_rcv_pdu(void *con, prs_struct *rdata);
> >
> > /* detect dead servers. The fd is set to -1 when we get an error */
> > BOOL rpc_con_ok(void *con);
> >
> > /* read and write to a pipe */
> > BOOL rpc_api_send_rcv_pdu(void *con, prs_struct *data,
> > prs_struct *rdata);
> >
> > } cli_connect_fns;
>
> This idea looks interesting, can you explain exactly
> how it would be used please, as I'm not sure of the
> exact semantics of these calls.
ok. the concept is taken directly from cli_connect.c: it was... um... 2
hours' work to create a cli_ncacn_np.c and a cli_ncalrpc.c which are each
about 140 lines long, including the GPL license :)
the purpose of this api is to act as a transport-independent DCE/RPC
communication system, one that can be asked at run-time to make decisions
on which transport is to be used. e.g, ncacn_np, ncalrpc, ncacn_tcp,
ncacn_http (which are SMB, loop-back, TCP and HTTP respectively).
[the _reason_ for adding it is to make it clearer what is going on. i
spent an hour and a half explaining the purpose of and the difference
between the ncacn_np and ncalrpc implementations. because it was not
clear, he removed large segments of code, in the interests of simplicity].
so, this api marks a clear delineation between transport-specific jobs and
the _use_ of the transports, which was otherwise embedded/hard-coded into
cli_connect.c with damn-stupid switch statements.
example.
the cli_ncacn_np.c cli_connect_add function calls ncacn_np_use_add().
this function will initiate an SMB IPC$ and perform an SMBopenX /
NTSMBcreateX on the DCE/RPC pipe name.
by contrast, the cli_ncalrpc.c cli_connect_add function calls
msrpc_use_add. this function will initiate a unix domain socket to
var/locks/.msrpc/DCERPCpipename.
by way of a further contrast, a cli_ncacn_tcp.c cli_connect_add function
will make a TCP connection to a [specified] port/ip address.
exactly what happens with ncacn_http, i am uncertain: we do have Netmon
traces and a sample program to generate ncacn_http (and we also have matty
:)
example.
the cli_ncacn_np.c rpc_api_rcv_pdu function calls cli_read() which sends
an SMBreadX.
the cli_ncalrpc.c rpc_api_rcv_pdu function calls msrpc_read() which calls
read_data(16), unmarshalls the PDU header and calls read_data(PDUsize) on
the unix domain socket to the DCE/RPC daemon.
> The only thing I'm not keen on here is the returning
> of (void *) as the type of a "con". I know it's the
> correct abstract data type thing to do, but I'd like
> to initially see the internal data type of "con" before
> deciding.
cli_connect_add() returns a void*. this is the state info required for
the connection. each impl., cli_ncacn_np.c, cli_ncalrpc.c,
cli_ncacn_tcp.c etc. will typecast its state to-and-fro. with 8 functions
and under 100 lines of code, it is hardly difficult to verify that the
typecasts are being done correctly:
/* create new connection. strictly speaking, one arg should be
* full dce/rpc format: e.g "ncacn_np:\\server\pipe\pipename" */
static void *ncacn_np_connect_add(const char *pipe_name,
const vuser_key * key,
const char *srv_name,
const struct ntuser_creds *ntc,
BOOL reuse, BOOL *is_new_connection)
{
return ncacn_np_use_add(pipe_name, NULL, srv_name,
ntc, reuse, is_new_connection);
}
/****************************************************************************
terminate client connection
****************************************************************************/
static void ncacn_np_connection_free(void *con_info)
{
struct ncacn_np *msrpc = (struct ncacn_np*)con_info;
BOOL closed = False;
DEBUG(10, ("msrpc smb connection\n"));
ncacn_np_use_del(msrpc->smb->desthost,
msrpc->pipe_name,
&msrpc->smb->nt.key, False, &closed);
}
/****************************************************************************
get nt creds (HACK ALERT!) associated with an msrpc session.
****************************************************************************/
static struct ntdom_info *ncacn_np_conn_get_ntinfo(void *con_info)
{
struct ncacn_np *msrpc = (struct ncacn_np*)con_info;
return &msrpc->smb->nt;
}
/****************************************************************************
get a server name associated with a connection associated with a
policy handle.
****************************************************************************/
static const char *ncacn_np_con_get_srvname(void *con_info)
{
struct ncacn_np *msrpc = (struct ncacn_np*)con_info;
return msrpc->smb->desthost;
}
/****************************************************************************
write to a pipe
****************************************************************************/
static BOOL ncacn_np_api_write(void *con_info, prs_struct *data)
{
struct ncacn_np *msrpc = (struct ncacn_np*)con_info;
struct cli_state *cli = msrpc->smb;
int fnum = msrpc->fnum;
return cli_write(cli, fnum, 0x0008,
data->data, 0,
prs_data_size(data), prs_data_size(data)) > 0;
}
static BOOL ncacn_np_api_rcv_pdu(struct cli_connection *con,
void *con_info, prs_struct *rdata)
{
struct ncacn_np *msrpc = (struct ncacn_np*)con_info;
struct cli_state *cli = msrpc->smb;
int fnum = msrpc->fnum;
return cli_rcv_pdu(con, cli, fnum, rdata);
}
/* this allows us to detect dead servers. The cli->fd is set to -1 when
we get an error */
static BOOL ncacn_np_con_ok(void *con_info)
{
struct ncacn_np *msrpc = (struct ncacn_np*)con_info;
struct cli_state *cli;
if (msrpc == NULL)
return False;
cli = msrpc->smb;
if (cli->fd == -1)
return False;
return True;
}
static BOOL ncacn_np_api_send_rcv_pdu(struct cli_connection *con,
void *con_info, prs_struct *data,
prs_struct *rdata)
{
struct ncacn_np *msrpc = (struct ncacn_np*)con_info;
struct ntdom_info *nt = ncacn_np_conn_get_ntinfo(con_info);
struct cli_state *cli = msrpc->smb;
int fnum = msrpc->fnum;
if (cli->fd == -1)
return False;
return cli_send_and_rcv_pdu(con, cli, fnum, data,
rdata, nt->max_xmit_frag);
}
static cli_connect_fns ncacn_np_fns =
{
ncacn_np_connect_add,
ncacn_np_connection_free,
ncacn_np_conn_get_ntinfo,
ncacn_np_con_get_srvname,
ncacn_np_api_write,
ncacn_np_api_rcv_pdu,
ncacn_np_con_ok,
ncacn_np_api_send_rcv_pdu
};
cli_connect_fns *ncacn_np_get_fns(void)
{
return &ncacn_np_fns;
}
More information about the samba-technical
mailing list