1
0
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:
Andrew Tridgell
-
parent 3706af7a6c
commit 5fb01b0ec0
7 changed files with 195 additions and 80 deletions

View File

@@ -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;
}
/*