2 Unix SMB/CIFS implementation.
3 default IPC$ NTVFS backend
5 Copyright (C) Andrew Tridgell 2003
6 Copyright (C) Stefan (metze) Metzmacher 2004
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 this implements the IPC$ backend, called by the NTVFS subsystem to
24 handle requests on IPC$ shares
30 /* this is the private structure used to keep the state of an open
31 ipc$ connection. It needs to keep information about all open
38 /* a list of open pipes */
40 struct pipe_state *next, *prev;
42 const char *pipe_name;
44 struct dcesrv_connection *dce_conn;
52 find the next fnum available on this connection
54 static uint16_t find_next_fnum(struct ipc_private *ipc)
59 if (ipc->num_open == 0xFFFF) {
64 ret = ipc->next_fnum++;
66 for (p=ipc->pipe_list; p; p=p->next) {
77 shutdown a single pipe. Called on a close or disconnect
79 static void pipe_shutdown(struct ipc_private *private, struct pipe_state *p)
81 TALLOC_CTX *mem_ctx = private->pipe_list->mem_ctx;
82 dcesrv_endpoint_disconnect(private->pipe_list->dce_conn);
83 DLIST_REMOVE(private->pipe_list, private->pipe_list);
84 talloc_destroy(mem_ctx);
89 find a open pipe give a file descriptor
91 static struct pipe_state *pipe_state_find(struct ipc_private *private, uint16_t fnum)
95 for (p=private->pipe_list; p; p=p->next) {
96 if (p->fnum == fnum) {
106 connect to a share - always works
108 static NTSTATUS ipc_connect(struct request_context *req, const char *sharename)
110 struct tcon_context *conn = req->conn;
111 struct ipc_private *private;
113 conn->fs_type = talloc_strdup(conn->mem_ctx, "IPC");
114 conn->dev_type = talloc_strdup(conn->mem_ctx, "IPC");
116 /* prepare the private state for this connection */
117 private = talloc(conn->mem_ctx, sizeof(struct ipc_private));
119 return NT_STATUS_NO_MEMORY;
121 conn->ntvfs_private = (void *)private;
123 private->pipe_list = NULL;
124 private->next_fnum = 1;
125 private->num_open = 0;
131 disconnect from a share
133 static NTSTATUS ipc_disconnect(struct tcon_context *tcon)
135 struct ipc_private *private = tcon->ntvfs_private;
137 /* close any pipes that are open. Discard any unread data */
138 while (private->pipe_list) {
139 pipe_shutdown(private, private->pipe_list);
148 static NTSTATUS ipc_unlink(struct request_context *req, struct smb_unlink *unl)
150 return NT_STATUS_ACCESS_DENIED;
155 ioctl interface - we don't do any
157 static NTSTATUS ipc_ioctl(struct request_context *req, union smb_ioctl *io)
159 return NT_STATUS_ACCESS_DENIED;
163 check if a directory exists
165 static NTSTATUS ipc_chkpath(struct request_context *req, struct smb_chkpath *cp)
167 return NT_STATUS_ACCESS_DENIED;
171 return info on a pathname
173 static NTSTATUS ipc_qpathinfo(struct request_context *req, union smb_fileinfo *info)
175 return NT_STATUS_ACCESS_DENIED;
179 set info on a pathname
181 static NTSTATUS ipc_setpathinfo(struct request_context *req, union smb_setfileinfo *st)
183 return NT_STATUS_ACCESS_DENIED;
189 open a file backend - used for MSRPC pipes
191 static NTSTATUS ipc_open_generic(struct request_context *req, const char *fname,
192 struct pipe_state **ps)
194 struct pipe_state *p;
197 struct dcesrv_ep_description ep_description;
198 struct ipc_private *private = req->conn->ntvfs_private;
200 mem_ctx = talloc_init("ipc_open '%s'", fname);
202 return NT_STATUS_NO_MEMORY;
205 p = talloc(mem_ctx, sizeof(struct pipe_state));
207 talloc_destroy(mem_ctx);
208 return NT_STATUS_NO_MEMORY;
210 p->mem_ctx = mem_ctx;
212 p->pipe_name = talloc_strdup(mem_ctx, fname);
214 talloc_destroy(mem_ctx);
215 return NT_STATUS_NO_MEMORY;
218 p->fnum = find_next_fnum(private);
220 talloc_destroy(mem_ctx);
221 return NT_STATUS_TOO_MANY_OPENED_FILES;
224 while (p->pipe_name[0] == '\\') {
227 p->ipc_state = 0x5ff;
230 we're all set, now ask the dcerpc server subsystem to open the
231 endpoint. At this stage the pipe isn't bound, so we don't
232 know what interface the user actually wants, just that they want
233 one of the interfaces attached to this pipe endpoint.
235 TODO: note that we aren't passing any credentials here. We
236 will need to do that once the credentials infrastructure is
240 ep_description.type = ENDPOINT_SMB;
241 ep_description.info.smb_pipe = p->pipe_name;
243 status = dcesrv_endpoint_search_connect(&req->smb->dcesrv, &ep_description, &p->dce_conn);
244 if (!NT_STATUS_IS_OK(status)) {
245 talloc_destroy(mem_ctx);
251 DLIST_ADD(private->pipe_list, p);
255 /* tell the RPC layer the transport session key */
256 if (req->user_ctx->vuser) {
257 dcesrv_set_session_key(p->dce_conn, req->user_ctx->vuser->session_key);
264 open a file with ntcreatex - used for MSRPC pipes
266 static NTSTATUS ipc_open_ntcreatex(struct request_context *req, union smb_open *oi)
268 struct pipe_state *p;
271 status = ipc_open_generic(req, oi->ntcreatex.in.fname, &p);
272 if (!NT_STATUS_IS_OK(status)) {
276 ZERO_STRUCT(oi->ntcreatex.out);
277 oi->ntcreatex.out.fnum = p->fnum;
278 oi->ntcreatex.out.ipc_state = p->ipc_state;
284 open a file with openx - used for MSRPC pipes
286 static NTSTATUS ipc_open_openx(struct request_context *req, union smb_open *oi)
288 struct pipe_state *p;
290 const char *fname = oi->openx.in.fname;
292 if (strncasecmp(fname, "PIPE\\", 5) != 0) {
293 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
298 status = ipc_open_generic(req, fname, &p);
299 if (!NT_STATUS_IS_OK(status)) {
303 ZERO_STRUCT(oi->openx.out);
304 oi->openx.out.fnum = p->fnum;
305 oi->openx.out.ftype = 2;
306 oi->openx.out.devstate = p->ipc_state;
312 open a file - used for MSRPC pipes
314 static NTSTATUS ipc_open(struct request_context *req, union smb_open *oi)
318 switch (oi->generic.level) {
319 case RAW_OPEN_NTCREATEX:
320 status = ipc_open_ntcreatex(req, oi);
323 status = ipc_open_openx(req, oi);
326 status = NT_STATUS_NOT_SUPPORTED;
336 static NTSTATUS ipc_mkdir(struct request_context *req, union smb_mkdir *md)
338 return NT_STATUS_ACCESS_DENIED;
344 static NTSTATUS ipc_rmdir(struct request_context *req, struct smb_rmdir *rd)
346 return NT_STATUS_ACCESS_DENIED;
350 rename a set of files
352 static NTSTATUS ipc_rename(struct request_context *req, union smb_rename *ren)
354 return NT_STATUS_ACCESS_DENIED;
360 static NTSTATUS ipc_copy(struct request_context *req, struct smb_copy *cp)
362 return NT_STATUS_ACCESS_DENIED;
368 static NTSTATUS ipc_read(struct request_context *req, union smb_read *rd)
370 struct ipc_private *private = req->conn->ntvfs_private;
373 struct pipe_state *p;
376 switch (rd->generic.level) {
378 fnum = rd->read.in.fnum;
379 data.length = rd->read.in.count;
380 data.data = rd->read.out.data;
383 fnum = rd->readx.in.fnum;
384 data.length = rd->readx.in.maxcnt;
385 data.data = rd->readx.out.data;
388 return NT_STATUS_NOT_SUPPORTED;
391 p = pipe_state_find(private, fnum);
393 return NT_STATUS_INVALID_HANDLE;
396 status = dcesrv_output_blob(p->dce_conn, &data);
397 if (!NT_STATUS_IS_OK(status)) {
401 switch (rd->generic.level) {
403 rd->read.out.nread = data.length;
406 rd->readx.out.remaining = 0;
407 rd->readx.out.compaction_mode = 0;
408 rd->readx.out.nread = data.length;
411 return NT_STATUS_NOT_SUPPORTED;
420 static NTSTATUS ipc_write(struct request_context *req, union smb_write *wr)
422 struct ipc_private *private = req->conn->ntvfs_private;
425 struct pipe_state *p;
428 switch (wr->generic.level) {
429 case RAW_WRITE_WRITE:
430 fnum = wr->write.in.fnum;
431 data.data = wr->write.in.data;
432 data.length = wr->write.in.count;
435 case RAW_WRITE_WRITEX:
436 fnum = wr->writex.in.fnum;
437 data.data = wr->writex.in.data;
438 data.length = wr->writex.in.count;
442 return NT_STATUS_NOT_SUPPORTED;
445 p = pipe_state_find(private, fnum);
447 return NT_STATUS_INVALID_HANDLE;
450 status = dcesrv_input(p->dce_conn, &data);
451 if (!NT_STATUS_IS_OK(status)) {
455 switch (wr->generic.level) {
456 case RAW_WRITE_WRITE:
457 wr->write.out.nwritten = data.length;
459 case RAW_WRITE_WRITEX:
460 wr->writex.out.nwritten = data.length;
461 wr->writex.out.remaining = 0;
464 return NT_STATUS_NOT_SUPPORTED;
473 static NTSTATUS ipc_seek(struct request_context *req, struct smb_seek *io)
475 return NT_STATUS_ACCESS_DENIED;
481 static NTSTATUS ipc_flush(struct request_context *req, struct smb_flush *io)
483 return NT_STATUS_ACCESS_DENIED;
489 static NTSTATUS ipc_close(struct request_context *req, union smb_close *io)
491 struct ipc_private *private = req->conn->ntvfs_private;
492 struct pipe_state *p;
494 if (io->generic.level != RAW_CLOSE_CLOSE) {
495 return NT_STATUS_ACCESS_DENIED;
498 p = pipe_state_find(private, io->close.in.fnum);
500 return NT_STATUS_INVALID_HANDLE;
503 pipe_shutdown(private, p);
510 exit - closing files?
512 static NTSTATUS ipc_exit(struct request_context *req)
514 return NT_STATUS_ACCESS_DENIED;
520 static NTSTATUS ipc_lock(struct request_context *req, union smb_lock *lck)
522 return NT_STATUS_ACCESS_DENIED;
526 set info on a open file
528 static NTSTATUS ipc_setfileinfo(struct request_context *req, union smb_setfileinfo *info)
530 return NT_STATUS_ACCESS_DENIED;
534 query info on a open file
536 static NTSTATUS ipc_qfileinfo(struct request_context *req, union smb_fileinfo *info)
538 return NT_STATUS_ACCESS_DENIED;
543 return filesystem info
545 static NTSTATUS ipc_fsinfo(struct request_context *req, union smb_fsinfo *fs)
547 return NT_STATUS_ACCESS_DENIED;
551 return print queue info
553 static NTSTATUS ipc_lpq(struct request_context *req, union smb_lpq *lpq)
555 return NT_STATUS_ACCESS_DENIED;
559 list files in a directory matching a wildcard pattern
561 NTSTATUS ipc_search_first(struct request_context *req, union smb_search_first *io,
562 void *search_private,
563 BOOL (*callback)(void *, union smb_search_data *))
565 return NT_STATUS_ACCESS_DENIED;
569 continue listing files in a directory
571 NTSTATUS ipc_search_next(struct request_context *req, union smb_search_next *io,
572 void *search_private,
573 BOOL (*callback)(void *, union smb_search_data *))
575 return NT_STATUS_ACCESS_DENIED;
579 end listing files in a directory
581 NTSTATUS ipc_search_close(struct request_context *req, union smb_search_close *io)
583 return NT_STATUS_ACCESS_DENIED;
587 /* SMBtrans - handle a DCERPC command */
588 static NTSTATUS ipc_dcerpc_cmd(struct request_context *req, struct smb_trans2 *trans)
590 struct pipe_state *p;
591 struct ipc_private *private = req->conn->ntvfs_private;
594 /* the fnum is in setup[1] */
595 p = pipe_state_find(private, trans->in.setup[1]);
597 return NT_STATUS_INVALID_HANDLE;
600 trans->out.data = data_blob_talloc(req->mem_ctx, NULL, trans->in.max_data);
601 if (!trans->out.data.data) {
602 return NT_STATUS_NO_MEMORY;
605 /* pass the data to the dcerpc server. Note that we don't
606 expect this to fail, and things like NDR faults are not
607 reported at this stage. Those sorts of errors happen in the
608 dcesrv_output stage */
609 status = dcesrv_input(p->dce_conn, &trans->in.data);
610 if (!NT_STATUS_IS_OK(status)) {
615 now ask the dcerpc system for some output. This doesn't yet handle
616 async calls. Again, we only expect NT_STATUS_OK. If the call fails then
617 the error is encoded at the dcerpc level
619 status = dcesrv_output_blob(p->dce_conn, &trans->out.data);
620 if (!NT_STATUS_IS_OK(status)) {
624 trans->out.setup_count = 0;
625 trans->out.setup = NULL;
626 trans->out.params = data_blob(NULL, 0);
632 /* SMBtrans - set named pipe state */
633 static NTSTATUS ipc_set_nm_pipe_state(struct request_context *req, struct smb_trans2 *trans)
635 struct pipe_state *p;
636 struct ipc_private *private = req->conn->ntvfs_private;
638 /* the fnum is in setup[1] */
639 p = pipe_state_find(private, trans->in.setup[1]);
641 return NT_STATUS_INVALID_HANDLE;
644 if (trans->in.params.length != 2) {
645 return NT_STATUS_INVALID_PARAMETER;
647 p->ipc_state = SVAL(trans->in.params.data, 0);
649 trans->out.setup_count = 0;
650 trans->out.setup = NULL;
651 trans->out.params = data_blob(NULL, 0);
652 trans->out.data = data_blob(NULL, 0);
658 /* SMBtrans - used to provide access to SMB pipes */
659 static NTSTATUS ipc_trans(struct request_context *req, struct smb_trans2 *trans)
663 if (trans->in.setup_count != 2) {
664 return NT_STATUS_INVALID_PARAMETER;
667 switch (trans->in.setup[0]) {
668 case TRANSACT_SETNAMEDPIPEHANDLESTATE:
669 status = ipc_set_nm_pipe_state(req, trans);
671 case TRANSACT_DCERPCCMD:
672 status = ipc_dcerpc_cmd(req, trans);
675 status = NT_STATUS_INVALID_PARAMETER;
685 initialialise the IPC backend, registering ourselves with the ntvfs subsystem
687 NTSTATUS ntvfs_ipc_init(void)
690 struct ntvfs_ops ops;
694 /* fill in the name and type */
695 ops.name = "default";
696 ops.type = NTVFS_IPC;
698 /* fill in all the operations */
699 ops.connect = ipc_connect;
700 ops.disconnect = ipc_disconnect;
701 ops.unlink = ipc_unlink;
702 ops.chkpath = ipc_chkpath;
703 ops.qpathinfo = ipc_qpathinfo;
704 ops.setpathinfo = ipc_setpathinfo;
706 ops.mkdir = ipc_mkdir;
707 ops.rmdir = ipc_rmdir;
708 ops.rename = ipc_rename;
710 ops.ioctl = ipc_ioctl;
712 ops.write = ipc_write;
714 ops.flush = ipc_flush;
715 ops.close = ipc_close;
718 ops.setfileinfo = ipc_setfileinfo;
719 ops.qfileinfo = ipc_qfileinfo;
720 ops.fsinfo = ipc_fsinfo;
722 ops.search_first = ipc_search_first;
723 ops.search_next = ipc_search_next;
724 ops.search_close = ipc_search_close;
725 ops.trans = ipc_trans;
727 /* register ourselves with the NTVFS subsystem. */
728 ret = register_backend("ntvfs", &ops);
730 if (!NT_STATUS_IS_OK(ret)) {
731 DEBUG(0,("Failed to register IPC backend!\n"));