default IPC$ NTVFS backend
Copyright (C) Andrew Tridgell 2003
- Copyright (C) Stefan (metze) Metzmacher 2004
+ Copyright (C) Stefan (metze) Metzmacher 2004-2005
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#include "includes.h"
-#include "system/filesys.h"
#include "dlinklist.h"
#include "smb_server/smb_server.h"
+#include "ntvfs/ntvfs.h"
+#include "rpc_server/dcerpc_server.h"
#define IPC_BASE_FNUM 0x400
struct ipc_private {
struct idr_context *idtree_fnum;
+ struct dcesrv_context *dcesrv;
+
/* a list of open pipes */
struct pipe_state {
struct pipe_state *next, *prev;
static NTSTATUS ipc_connect(struct ntvfs_module_context *ntvfs,
struct smbsrv_request *req, const char *sharename)
{
+ NTSTATUS status;
struct smbsrv_tcon *tcon = req->tcon;
struct ipc_private *private;
tcon->fs_type = talloc_strdup(tcon, "IPC");
+ NT_STATUS_HAVE_NO_MEMORY(tcon->fs_type);
+
tcon->dev_type = talloc_strdup(tcon, "IPC");
+ NT_STATUS_HAVE_NO_MEMORY(tcon->dev_type);
/* prepare the private state for this connection */
- private = talloc_p(tcon, struct ipc_private);
- if (!private) {
- return NT_STATUS_NO_MEMORY;
- }
+ private = talloc(tcon, struct ipc_private);
+ NT_STATUS_HAVE_NO_MEMORY(private);
+
ntvfs->private_data = private;
private->pipe_list = NULL;
private->idtree_fnum = idr_init(private);
- if (private->idtree_fnum == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
+ NT_STATUS_HAVE_NO_MEMORY(private->idtree_fnum);
+
+ /* setup the DCERPC server subsystem */
+ status = dcesrv_init_ipc_context(private, &private->dcesrv);
+ NT_STATUS_NOT_OK_RETURN(status);
return NT_STATUS_OK;
}
static NTSTATUS ipc_disconnect(struct ntvfs_module_context *ntvfs,
struct smbsrv_tcon *tcon)
{
- struct ipc_private *private = ntvfs->private_data;
-
- /* close any pipes that are open. Discard any unread data */
- while (private->pipe_list) {
- talloc_free(private->pipe_list);
- }
-
return NT_STATUS_OK;
}
struct pipe_state *p = ptr;
idr_remove(p->private->idtree_fnum, p->fnum);
DLIST_REMOVE(p->private->pipe_list, p);
- talloc_free(p->dce_conn);
return 0;
}
{
struct pipe_state *p;
NTSTATUS status;
- struct dcerpc_binding ep_description;
- struct auth_session_info *session_info = NULL;
+ struct dcerpc_binding *ep_description;
struct ipc_private *private = ntvfs->private_data;
int fnum;
+ struct stream_connection *srv_conn = req->smb_conn->connection;
- p = talloc_p(req, struct pipe_state);
- if (!p) {
- return NT_STATUS_NO_MEMORY;
+ if (!req->session || !req->session->session_info) {
+ return NT_STATUS_ACCESS_DENIED;
}
+ p = talloc(req, struct pipe_state);
+ NT_STATUS_HAVE_NO_MEMORY(p);
+
+ ep_description = talloc(req, struct dcerpc_binding);
+ NT_STATUS_HAVE_NO_MEMORY(ep_description);
+
while (fname[0] == '\\') fname++;
p->pipe_name = talloc_asprintf(p, "\\pipe\\%s", fname);
- if (!p->pipe_name) {
- return NT_STATUS_NO_MEMORY;
- }
+ NT_STATUS_HAVE_NO_MEMORY(p->pipe_name);
fnum = idr_get_new_above(private->idtree_fnum, p, IPC_BASE_FNUM, UINT16_MAX);
if (fnum == -1) {
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
*/
- ep_description.transport = NCACN_NP;
- ep_description.endpoint = p->pipe_name;
-
- /* tell the RPC layer the session_info */
- if (req->session) {
- /* The session info is refcount-increased in the
- dcesrv_endpoint_search_connect() function */
- session_info = req->session->session_info;
- }
-
- status = dcesrv_endpoint_search_connect(req->smb_conn->dcesrv,
- &ep_description,
- session_info,
+ ep_description->transport = NCACN_NP;
+ ep_description->endpoint = talloc_reference(ep_description, p->pipe_name);
+
+ /* The session info is refcount-increased in the
+ * dcesrv_endpoint_search_connect() function
+ */
+ status = dcesrv_endpoint_search_connect(private->dcesrv,
+ p,
+ ep_description,
+ req->session->session_info,
+ srv_conn,
&p->dce_conn);
if (!NT_STATUS_IS_OK(status)) {
idr_remove(private->idtree_fnum, p->fnum);
ZERO_STRUCT(oi->ntcreatex.out);
oi->ntcreatex.out.fnum = p->fnum;
oi->ntcreatex.out.ipc_state = p->ipc_state;
+ oi->ntcreatex.out.file_type = FILE_TYPE_MESSAGE_MODE_PIPE;
return status;
}
return NT_STATUS_ACCESS_DENIED;
}
+static NTSTATUS ipc_readx_dcesrv_output(void *private_data, DATA_BLOB *out, size_t *nwritten)
+{
+ DATA_BLOB *blob = private_data;
+
+ if (out->length < blob->length) {
+ blob->length = out->length;
+ }
+ memcpy(blob->data, out->data, blob->length);
+ *nwritten = blob->length;
+ return NT_STATUS_OK;
+}
+
/*
read from a file
*/
DATA_BLOB data;
uint16_t fnum;
struct pipe_state *p;
- NTSTATUS status;
+ NTSTATUS status = NT_STATUS_OK;
if (rd->generic.level != RAW_READ_GENERIC) {
return ntvfs_map_read(req, rd, ntvfs);
data.length = rd->readx.in.maxcnt;
data.data = rd->readx.out.data;
if (data.length > UINT16_MAX) {
- data.length = 0;
+ data.length = UINT16_MAX;
}
if (data.length != 0) {
- status = dcesrv_output_blob(p->dce_conn, &data);
+ status = dcesrv_output(p->dce_conn, &data, ipc_readx_dcesrv_output);
if (NT_STATUS_IS_ERR(status)) {
return status;
}
return NT_STATUS_ACCESS_DENIED;
}
+static NTSTATUS ipc_trans_dcesrv_output(void *private_data, DATA_BLOB *out, size_t *nwritten)
+{
+ NTSTATUS status = NT_STATUS_OK;
+ DATA_BLOB *blob = private_data;
+
+ if (out->length > blob->length) {
+ status = STATUS_BUFFER_OVERFLOW;
+ }
+
+ if (out->length < blob->length) {
+ blob->length = out->length;
+ }
+ memcpy(blob->data, out->data, blob->length);
+ *nwritten = blob->length;
+ return status;
+}
/* SMBtrans - handle a DCERPC command */
static NTSTATUS ipc_dcerpc_cmd(struct ntvfs_module_context *ntvfs,
async calls. Again, we only expect NT_STATUS_OK. If the call fails then
the error is encoded at the dcerpc level
*/
- status = dcesrv_output_blob(p->dce_conn, &trans->out.data);
+ status = dcesrv_output(p->dce_conn, &trans->out.data, ipc_trans_dcesrv_output);
if (NT_STATUS_IS_ERR(status)) {
return status;
}