smb_rpc.c revision 8c10a8659ac31335ed870a1711c0182623f72fd6
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* This module provides a set of wrapper functions to interface to the
* RPC layer. Although this interface was originally implemented as a
* single transaction using an input buffer and an output buffer, it
* This was first discovered when we noticed that Windows2000 was using
* smb_rpc_write and smb_rpc_read instead of smb_rpc_transact and then
* later when we tried to return a larger number of shares than would
* fit in a single transaction buffer.
*
* The interface is still limited by the buffers passed between this
* module and the RPC module but now it will support a buffer overflow
* and allow the client to read the remaining data on subsequent
* requests. Also note that the smb_rpc_write and smb_rpc_read calls
* are basically emulating the smb_rpc_transact function.
*/
#include <smbsrv/smb_incl.h>
/*
* This is the list of well-known RPC named pipes that we support.
* The full pipe path will be in the form \\PIPE\\SERVICE. The first
* part can be assumed, so all we need here are the service names.
*/
static char *rpc_named_pipes[] = {
"\\LSARPC",
"\\NETLOGON",
"\\SAMR",
"\\SPOOLSS",
"\\SRVSVC",
"\\SVCCTL",
"\\WINREG",
"\\WKSSVC",
"\\EVENTLOG"
};
/*
* This is a list of the port addresses for the named pipes above.
* We need to check that these are correct but nothing appears to
* rely on them so this is low priority.
*/
#if 0
static char *rpc_np_ports[] = {
"\\PIPE\\",
"\\PIPE\\lsass",
"\\PIPE\\lsass",
"\\PIPE\\spoolss",
"\\PIPE\\ntsvcs",
"\\PIPE\\ntsvcs",
"\\PIPE\\winreg",
"\\PIPE\\ntsvcs",
"\\PIPE\\ntsvcs"
};
#endif
static uint32_t smb_rpc_fid(void);
/*
* Named pipe I/O is serialized to ensure that each request has exclusive
* access to the in and out pipe data for the duration of the request.
*/
static void
{
}
static void
{
}
/*
* smb_rpc_lookup
*
* Lookup a path to see if it's a well-known RPC named pipe.
*
* Returns a pointer to the pipe name (without any leading \'s) if the path
* refers to a well-known RPC named pipe. Otherwise returns a null pointer.
*/
char *
smb_rpc_lookup(char *path)
{
int i;
char *pipe_name;
if (path == 0) {
return (0);
}
/*
* Skip past the static part of the pipe
* name if it appears in the path.
*/
path += 5;
for (i = 0;
i < sizeof (rpc_named_pipes) / sizeof (rpc_named_pipes[0]);
++i) {
pipe_name = rpc_named_pipes[i];
return (pipe_name);
}
}
return (0);
}
/*
* smb_rpc_open
*
* Open a well-known RPC named pipe. This routine should be called if
* a file open is requested on a share of type STYPE_IPC. If we
* recognize the pipe, we initialize the session data. This will setup
* a new ofile and insert it into the session file list.
*
* Returns 0 on success, Otherwise an NT status is returned to indicate
* an error.
*/
int
{
struct open_param *op;
char *pipe_name;
int status;
return (status);
return (NT_STATUS_SUCCESS);
}
return (NT_STATUS_OBJECT_NAME_NOT_FOUND);
}
/*
* smb_rpc_initialize
*
* Initialize various parts of the session data for a named pipe: open
* parameters and the ofile. There are a number of magic numbers in
* here that we need to identify but largely these values are ignored
* by the rest of the code. Insert the ofile into the session file list.
*
* Returns 0 on success, Otherwise an NT status is returned to indicate
* an error.
*/
static int
{
struct open_param *op;
SMB_UNIQ_FID(), &err);
| SMB_PIPE_UNLIMITED_INSTANCES; /* 0x05ff */
op->create_options = 0;
return (0);
}
/*
* smb_rpc_transact
*
* This is the entry point for RPC transactions to provide a wrapper for
* the RPC layer. The SMB decoding and encoding is handled here so that
* the RPC layer doesn't have to deal with it. Both bind operations and
* RPC requests are handled here. The connection_fid is an arbitrary id
* used to associate RPC requests with a particular binding handle.
*
* The RPC library expects the input stream to contain the request data.
* It will build the output stream.
*
* If the data to be returned is larger than the client expects, we
* return as much as the client can handle and report a buffer overflow
* warning to inform the client that we have more data to return. The
* residual data remains in the output stream until the client claims
* it or closes the pipe.
*/
{
int mdrcnt;
int nbytes;
int rc;
return (SDRC_ERROR);
}
if (rc != 0) {
0, 0);
return (SDRC_ERROR);
}
/*
* We need to zero the input stream so that we don't try to
* flush it on close: the mbuf chain belongs to the SMB XA.
*/
/*
* We have more data to return than the client expects in the
* response to this request. So we send as much as the client
* can handle, mdrcnt, and store the rest in the output chain.
* The buffer overflow warning informs the client that we
* have more data to send. Typically, the client will call
* SmbRead&X, which will call smb_rpc_read, to get the data.
*/
} else {
/*
* The client has provided enough buffer space, all
* we have to do is attach the output stream to the
* transaction response and zero out the stream.
*/
if (nbytes != 0) {
}
}
}
return (SDRC_SUCCESS);
}
/*
* smb_rpc_fid
*
* The connection_fid is an arbitrary id used to associate RPC requests
* with a particular binding handle. This routine provides a new fid on
* each call. It will not assign 0 or -1 so that those values can
* remain available as sentinels.
*/
static uint32_t
smb_rpc_fid(void)
{
static uint32_t connection_fid;
static kmutex_t smb_rpc_fid_mutex;
if (connection_fid == 0)
do {
return (connection_fid);
}
/*
* smb_rpc_close
*
* All remaining I/O is flushed and the RPC layer is informed so that
* it can release the resources being used for this connection.
*/
void
{
}
}
}
/*
* smb_rpc_write
*
* This interface is an alternative to smb_rpc_transact. We set up the
* connection fid, as required, and copy the input data to the input
* stream. The input stream is created by allocating enough mbufs to
* hold the incoming data and doing a uio transfer. It is then up
* to the client to call smb_rpc_read to actually make the transaction
* happen.
*
* Returns 0 on success or an errno on failure.
*/
int
{
int rc;
return (EBADF);
}
}
/*
* smb_rpc_read
*
* This interface may be called because smb_rpc_transact could not return
* all of the data in the original transaction or to form the second half
* of a transaction set up using smb_rpc_write. If there is data in the
* output stream, we return it. Otherwise we assume that there is data
* in the input stream that will provide the context to perform an RPC
* transaction. The connection fid (pipe_info->fid) will provide the
* context for mlsvc_rpc_process.
*
* The response data is encoded into raw_data as required by the smb_read
* functions. The uio_resid value indicates the number of bytes read.
*/
/*ARGSUSED*/
int
{
int mdrcnt;
int nbytes;
int rc = 0;
goto smb_rpc_read_exit;
}
/*
* if there is data left in the outpipe return it now
*/
streamin = 0;
goto smb_rpc_read_exit;
}
}
}
return (rc);
}