mirror of
https://github.com/samba-team/samba.git
synced 2025-10-21 03:33:16 +03:00
the rest of the initial rpc server side infrastructure
This commit is contained in:
@@ -25,16 +25,102 @@
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
/* this is the private structure used to keep the state of an open
|
||||
ipc$ connection. It needs to keep information about all open
|
||||
pipes */
|
||||
struct ipc_private {
|
||||
|
||||
uint16 next_fnum;
|
||||
uint16 num_open;
|
||||
|
||||
/* a list of open pipes */
|
||||
struct pipe_state {
|
||||
struct pipe_state *next, *prev;
|
||||
TALLOC_CTX *mem_ctx;
|
||||
const char *pipe_name;
|
||||
uint16 fnum;
|
||||
struct dcesrv_state *pipe_state;
|
||||
} *pipe_list;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
find the next fnum available on this connection
|
||||
*/
|
||||
static uint16 find_next_fnum(struct ipc_private *ipc)
|
||||
{
|
||||
struct pipe_state *p;
|
||||
uint32 ret;
|
||||
|
||||
if (ipc->num_open == 0xFFFF) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
again:
|
||||
ret = ipc->next_fnum++;
|
||||
|
||||
for (p=ipc->pipe_list; p; p=p->next) {
|
||||
if (p->fnum == ret) {
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
shutdown a single pipe. Called on a close or disconnect
|
||||
*/
|
||||
static void pipe_shutdown(struct ipc_private *private, struct pipe_state *p)
|
||||
{
|
||||
TALLOC_CTX *mem_ctx = private->pipe_list->mem_ctx;
|
||||
dcesrv_endpoint_disconnect(private->pipe_list->pipe_state);
|
||||
DLIST_REMOVE(private->pipe_list, private->pipe_list);
|
||||
talloc_destroy(mem_ctx);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
find a open pipe give a file descriptor
|
||||
*/
|
||||
static struct pipe_state *pipe_state_find(struct ipc_private *private, uint16 fnum)
|
||||
{
|
||||
struct pipe_state *p;
|
||||
|
||||
for (p=private->pipe_list; p; p=p->next) {
|
||||
if (p->fnum == fnum) {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
connect to a share - always works
|
||||
*/
|
||||
static NTSTATUS ipc_connect(struct request_context *req, const char *sharename)
|
||||
{
|
||||
struct tcon_context *conn = req->conn;
|
||||
struct ipc_private *private;
|
||||
|
||||
conn->fs_type = talloc_strdup(conn->mem_ctx, "IPC");
|
||||
conn->dev_type = talloc_strdup(conn->mem_ctx, "IPC");
|
||||
|
||||
/* prepare the private state for this connection */
|
||||
private = talloc(conn->mem_ctx, sizeof(struct ipc_private));
|
||||
if (!private) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
conn->ntvfs_private = (void *)private;
|
||||
|
||||
private->pipe_list = NULL;
|
||||
private->next_fnum = 1;
|
||||
private->num_open = 0;
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
@@ -43,6 +129,13 @@ static NTSTATUS ipc_connect(struct request_context *req, const char *sharename)
|
||||
*/
|
||||
static NTSTATUS ipc_disconnect(struct tcon_context *tcon)
|
||||
{
|
||||
struct ipc_private *private = tcon->ntvfs_private;
|
||||
|
||||
/* close any pipes that are open. Discard any unread data */
|
||||
while (private->pipe_list) {
|
||||
pipe_shutdown(private, private->pipe_list);
|
||||
}
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
@@ -88,11 +181,79 @@ static NTSTATUS ipc_setpathinfo(struct request_context *req, union smb_setfilein
|
||||
}
|
||||
|
||||
/*
|
||||
open a file
|
||||
open a file - used for MSRPC pipes
|
||||
*/
|
||||
static NTSTATUS ipc_open(struct request_context *req, union smb_open *oi)
|
||||
{
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
struct pipe_state *p;
|
||||
TALLOC_CTX *mem_ctx;
|
||||
NTSTATUS status;
|
||||
struct dcesrv_endpoint endpoint;
|
||||
struct ipc_private *private = req->conn->ntvfs_private;
|
||||
|
||||
/* for now only handle NTcreateX style opens */
|
||||
if (oi->generic.level != RAW_OPEN_NTCREATEX) {
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
mem_ctx = talloc_init("ipc_open '%s'", oi->ntcreatex.in.fname);
|
||||
if (!mem_ctx) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
p = talloc(mem_ctx, sizeof(struct pipe_state));
|
||||
if (!p) {
|
||||
talloc_destroy(mem_ctx);
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
p->mem_ctx = mem_ctx;
|
||||
|
||||
p->pipe_name = talloc_strdup(mem_ctx, oi->ntcreatex.in.fname);
|
||||
if (!p->pipe_name) {
|
||||
talloc_destroy(mem_ctx);
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
p->fnum = find_next_fnum(private);
|
||||
if (p->fnum == 0) {
|
||||
talloc_destroy(mem_ctx);
|
||||
return NT_STATUS_TOO_MANY_OPENED_FILES;
|
||||
}
|
||||
|
||||
if (strncasecmp(p->pipe_name, "\\pipe\\", 6) != 0) {
|
||||
talloc_destroy(mem_ctx);
|
||||
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
}
|
||||
p->pipe_name += 6;
|
||||
|
||||
/*
|
||||
we're all set, now ask the dcerpc server subsystem to open the
|
||||
endpoint. At this stage the pipe isn't bound, so we don't
|
||||
know what interface the user actually wants, just that they want
|
||||
one of the interfaces attached to this pipe endpoint.
|
||||
|
||||
TODO: note that we aren't passing any credentials here. We
|
||||
will need to do that once the credentials infrastructure is
|
||||
finalised for Samba4
|
||||
*/
|
||||
|
||||
endpoint.type = ENDPOINT_SMB;
|
||||
endpoint.info.smb_pipe = p->pipe_name;
|
||||
|
||||
status = dcesrv_endpoint_connect(req->smb, &endpoint, &p->pipe_state);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
talloc_destroy(mem_ctx);
|
||||
return status;
|
||||
}
|
||||
|
||||
private->num_open++;
|
||||
|
||||
DLIST_ADD(private->pipe_list, p);
|
||||
|
||||
ZERO_STRUCT(oi->ntcreatex.out);
|
||||
oi->ntcreatex.out.fnum = p->fnum;
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -164,7 +325,22 @@ static NTSTATUS ipc_flush(struct request_context *req, struct smb_flush *io)
|
||||
*/
|
||||
static NTSTATUS ipc_close(struct request_context *req, union smb_close *io)
|
||||
{
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
struct ipc_private *private = req->conn->ntvfs_private;
|
||||
struct pipe_state *p;
|
||||
|
||||
if (io->generic.level != RAW_CLOSE_CLOSE) {
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
p = pipe_state_find(private, io->close.in.fnum);
|
||||
if (!p) {
|
||||
return NT_STATUS_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
pipe_shutdown(private, p);
|
||||
private->num_open--;
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
|
Reference in New Issue
Block a user