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
29 #include "system/filesys.h"
31 /* this is the private structure used to keep the state of an open
32 ipc$ connection. It needs to keep information about all open
35 struct idr_context *idtree_fnum;
37 /* a list of open pipes */
39 struct pipe_state *next, *prev;
40 struct ipc_private *private;
41 const char *pipe_name;
43 struct dcesrv_connection *dce_conn;
45 /* we need to remember the session it was opened on,
46 as it is illegal to operate on someone elses fnum */
47 struct smbsrv_session *session;
49 /* we need to remember the client pid that
50 opened the file so SMBexit works */
58 find a open pipe give a file descriptor
60 static struct pipe_state *pipe_state_find(struct ipc_private *private, uint16_t fnum)
62 return idr_find(private->idtree_fnum, fnum);
67 connect to a share - always works
69 static NTSTATUS ipc_connect(struct ntvfs_module_context *ntvfs,
70 struct smbsrv_request *req, const char *sharename)
72 struct smbsrv_tcon *tcon = req->tcon;
73 struct ipc_private *private;
75 tcon->fs_type = talloc_strdup(tcon, "IPC");
76 tcon->dev_type = talloc_strdup(tcon, "IPC");
78 /* prepare the private state for this connection */
79 private = talloc_p(tcon, struct ipc_private);
81 return NT_STATUS_NO_MEMORY;
83 ntvfs->private_data = private;
85 private->pipe_list = NULL;
87 private->idtree_fnum = idr_init(private);
88 if (private->idtree_fnum == NULL) {
89 return NT_STATUS_NO_MEMORY;
96 disconnect from a share
98 static NTSTATUS ipc_disconnect(struct ntvfs_module_context *ntvfs,
99 struct smbsrv_tcon *tcon)
101 struct ipc_private *private = ntvfs->private_data;
103 /* close any pipes that are open. Discard any unread data */
104 while (private->pipe_list) {
105 talloc_free(private->pipe_list);
114 static NTSTATUS ipc_unlink(struct ntvfs_module_context *ntvfs,
115 struct smbsrv_request *req, struct smb_unlink *unl)
117 return NT_STATUS_ACCESS_DENIED;
122 ioctl interface - we don't do any
124 static NTSTATUS ipc_ioctl(struct ntvfs_module_context *ntvfs,
125 struct smbsrv_request *req, union smb_ioctl *io)
127 return NT_STATUS_ACCESS_DENIED;
131 check if a directory exists
133 static NTSTATUS ipc_chkpath(struct ntvfs_module_context *ntvfs,
134 struct smbsrv_request *req, struct smb_chkpath *cp)
136 return NT_STATUS_ACCESS_DENIED;
140 return info on a pathname
142 static NTSTATUS ipc_qpathinfo(struct ntvfs_module_context *ntvfs,
143 struct smbsrv_request *req, union smb_fileinfo *info)
145 return NT_STATUS_ACCESS_DENIED;
149 set info on a pathname
151 static NTSTATUS ipc_setpathinfo(struct ntvfs_module_context *ntvfs,
152 struct smbsrv_request *req, union smb_setfileinfo *st)
154 return NT_STATUS_ACCESS_DENIED;
159 destroy a open pipe structure
161 static int ipc_fd_destructor(void *ptr)
163 struct pipe_state *p = ptr;
164 idr_remove(p->private->idtree_fnum, p->fnum);
165 DLIST_REMOVE(p->private->pipe_list, p);
166 talloc_free(p->dce_conn);
172 open a file backend - used for MSRPC pipes
174 static NTSTATUS ipc_open_generic(struct ntvfs_module_context *ntvfs,
175 struct smbsrv_request *req, const char *fname,
176 struct pipe_state **ps)
178 struct pipe_state *p;
180 struct dcerpc_binding ep_description;
181 struct auth_session_info *session_info = NULL;
182 struct ipc_private *private = ntvfs->private_data;
185 p = talloc_p(req, struct pipe_state);
187 return NT_STATUS_NO_MEMORY;
190 while (fname[0] == '\\') fname++;
192 p->pipe_name = talloc_asprintf(p, "\\pipe\\%s", fname);
194 return NT_STATUS_NO_MEMORY;
197 fnum = idr_get_new(private->idtree_fnum, p, UINT16_MAX);
199 return NT_STATUS_TOO_MANY_OPENED_FILES;
203 p->ipc_state = 0x5ff;
206 we're all set, now ask the dcerpc server subsystem to open the
207 endpoint. At this stage the pipe isn't bound, so we don't
208 know what interface the user actually wants, just that they want
209 one of the interfaces attached to this pipe endpoint.
211 TODO: note that we aren't passing any credentials here. We
212 will need to do that once the credentials infrastructure is
215 ep_description.transport = NCACN_NP;
216 ep_description.endpoint = p->pipe_name;
218 /* tell the RPC layer the session_info */
220 /* The session info is refcount-increased in the
221 dcesrv_endpoint_search_connect() function */
222 session_info = req->session->session_info;
225 status = dcesrv_endpoint_search_connect(req->smb_conn->dcesrv,
229 if (!NT_STATUS_IS_OK(status)) {
230 idr_remove(private->idtree_fnum, p->fnum);
234 DLIST_ADD(private->pipe_list, p);
236 p->smbpid = req->smbpid;
237 p->session = req->session;
238 p->private = private;
242 talloc_steal(private, p);
244 talloc_set_destructor(p, ipc_fd_destructor);
250 open a file with ntcreatex - used for MSRPC pipes
252 static NTSTATUS ipc_open_ntcreatex(struct ntvfs_module_context *ntvfs,
253 struct smbsrv_request *req, union smb_open *oi)
255 struct pipe_state *p;
258 status = ipc_open_generic(ntvfs, req, oi->ntcreatex.in.fname, &p);
259 if (!NT_STATUS_IS_OK(status)) {
263 ZERO_STRUCT(oi->ntcreatex.out);
264 oi->ntcreatex.out.fnum = p->fnum;
265 oi->ntcreatex.out.ipc_state = p->ipc_state;
271 open a file with openx - used for MSRPC pipes
273 static NTSTATUS ipc_open_openx(struct ntvfs_module_context *ntvfs,
274 struct smbsrv_request *req, union smb_open *oi)
276 struct pipe_state *p;
278 const char *fname = oi->openx.in.fname;
280 status = ipc_open_generic(ntvfs, req, fname, &p);
281 if (!NT_STATUS_IS_OK(status)) {
285 ZERO_STRUCT(oi->openx.out);
286 oi->openx.out.fnum = p->fnum;
287 oi->openx.out.ftype = 2;
288 oi->openx.out.devstate = p->ipc_state;
294 open a file - used for MSRPC pipes
296 static NTSTATUS ipc_open(struct ntvfs_module_context *ntvfs,
297 struct smbsrv_request *req, union smb_open *oi)
301 switch (oi->generic.level) {
302 case RAW_OPEN_NTCREATEX:
303 status = ipc_open_ntcreatex(ntvfs, req, oi);
306 status = ipc_open_openx(ntvfs, req, oi);
309 status = NT_STATUS_NOT_SUPPORTED;
319 static NTSTATUS ipc_mkdir(struct ntvfs_module_context *ntvfs,
320 struct smbsrv_request *req, union smb_mkdir *md)
322 return NT_STATUS_ACCESS_DENIED;
328 static NTSTATUS ipc_rmdir(struct ntvfs_module_context *ntvfs,
329 struct smbsrv_request *req, struct smb_rmdir *rd)
331 return NT_STATUS_ACCESS_DENIED;
335 rename a set of files
337 static NTSTATUS ipc_rename(struct ntvfs_module_context *ntvfs,
338 struct smbsrv_request *req, union smb_rename *ren)
340 return NT_STATUS_ACCESS_DENIED;
346 static NTSTATUS ipc_copy(struct ntvfs_module_context *ntvfs,
347 struct smbsrv_request *req, struct smb_copy *cp)
349 return NT_STATUS_ACCESS_DENIED;
355 static NTSTATUS ipc_read(struct ntvfs_module_context *ntvfs,
356 struct smbsrv_request *req, union smb_read *rd)
358 struct ipc_private *private = ntvfs->private_data;
361 struct pipe_state *p;
364 if (rd->generic.level != RAW_READ_GENERIC) {
365 return ntvfs_map_read(req, rd, ntvfs);
368 fnum = rd->readx.in.fnum;
370 p = pipe_state_find(private, fnum);
372 return NT_STATUS_INVALID_HANDLE;
375 data.length = rd->readx.in.maxcnt;
376 data.data = rd->readx.out.data;
377 if (data.length > UINT16_MAX) {
381 if (data.length != 0) {
382 status = dcesrv_output_blob(p->dce_conn, &data);
383 if (NT_STATUS_IS_ERR(status)) {
388 rd->readx.out.remaining = 0;
389 rd->readx.out.compaction_mode = 0;
390 rd->readx.out.nread = data.length;
398 static NTSTATUS ipc_write(struct ntvfs_module_context *ntvfs,
399 struct smbsrv_request *req, union smb_write *wr)
401 struct ipc_private *private = ntvfs->private_data;
404 struct pipe_state *p;
407 if (wr->generic.level != RAW_WRITE_GENERIC) {
408 return ntvfs_map_write(req, wr, ntvfs);
411 fnum = wr->writex.in.fnum;
412 data.data = discard_const_p(void, wr->writex.in.data);
413 data.length = wr->writex.in.count;
415 p = pipe_state_find(private, fnum);
417 return NT_STATUS_INVALID_HANDLE;
420 status = dcesrv_input(p->dce_conn, &data);
421 if (!NT_STATUS_IS_OK(status)) {
425 wr->writex.out.nwritten = data.length;
426 wr->writex.out.remaining = 0;
434 static NTSTATUS ipc_seek(struct ntvfs_module_context *ntvfs,
435 struct smbsrv_request *req, struct smb_seek *io)
437 return NT_STATUS_ACCESS_DENIED;
443 static NTSTATUS ipc_flush(struct ntvfs_module_context *ntvfs,
444 struct smbsrv_request *req, struct smb_flush *io)
446 return NT_STATUS_ACCESS_DENIED;
452 static NTSTATUS ipc_close(struct ntvfs_module_context *ntvfs,
453 struct smbsrv_request *req, union smb_close *io)
455 struct ipc_private *private = ntvfs->private_data;
456 struct pipe_state *p;
458 if (io->generic.level != RAW_CLOSE_CLOSE) {
459 return ntvfs_map_close(req, io, ntvfs);
462 p = pipe_state_find(private, io->close.in.fnum);
464 return NT_STATUS_INVALID_HANDLE;
475 static NTSTATUS ipc_exit(struct ntvfs_module_context *ntvfs,
476 struct smbsrv_request *req)
478 struct ipc_private *private = ntvfs->private_data;
479 struct pipe_state *p, *next;
481 for (p=private->pipe_list; p; p=next) {
483 if (p->smbpid == req->smbpid) {
492 logoff - closing files open by the user
494 static NTSTATUS ipc_logoff(struct ntvfs_module_context *ntvfs,
495 struct smbsrv_request *req)
497 struct ipc_private *private = ntvfs->private_data;
498 struct pipe_state *p, *next;
500 for (p=private->pipe_list; p; p=next) {
502 if (p->session == req->session) {
511 setup for an async call
513 static NTSTATUS ipc_async_setup(struct ntvfs_module_context *ntvfs,
514 struct smbsrv_request *req,
523 static NTSTATUS ipc_lock(struct ntvfs_module_context *ntvfs,
524 struct smbsrv_request *req, union smb_lock *lck)
526 return NT_STATUS_ACCESS_DENIED;
530 set info on a open file
532 static NTSTATUS ipc_setfileinfo(struct ntvfs_module_context *ntvfs,
533 struct smbsrv_request *req, union smb_setfileinfo *info)
535 return NT_STATUS_ACCESS_DENIED;
539 query info on a open file
541 static NTSTATUS ipc_qfileinfo(struct ntvfs_module_context *ntvfs,
542 struct smbsrv_request *req, union smb_fileinfo *info)
544 return NT_STATUS_ACCESS_DENIED;
549 return filesystem info
551 static NTSTATUS ipc_fsinfo(struct ntvfs_module_context *ntvfs,
552 struct smbsrv_request *req, union smb_fsinfo *fs)
554 return NT_STATUS_ACCESS_DENIED;
558 return print queue info
560 static NTSTATUS ipc_lpq(struct ntvfs_module_context *ntvfs,
561 struct smbsrv_request *req, union smb_lpq *lpq)
563 return NT_STATUS_ACCESS_DENIED;
567 list files in a directory matching a wildcard pattern
569 static NTSTATUS ipc_search_first(struct ntvfs_module_context *ntvfs,
570 struct smbsrv_request *req, union smb_search_first *io,
571 void *search_private,
572 BOOL (*callback)(void *, union smb_search_data *))
574 return NT_STATUS_ACCESS_DENIED;
578 continue listing files in a directory
580 static NTSTATUS ipc_search_next(struct ntvfs_module_context *ntvfs,
581 struct smbsrv_request *req, union smb_search_next *io,
582 void *search_private,
583 BOOL (*callback)(void *, union smb_search_data *))
585 return NT_STATUS_ACCESS_DENIED;
589 end listing files in a directory
591 static NTSTATUS ipc_search_close(struct ntvfs_module_context *ntvfs,
592 struct smbsrv_request *req, union smb_search_close *io)
594 return NT_STATUS_ACCESS_DENIED;
598 /* SMBtrans - handle a DCERPC command */
599 static NTSTATUS ipc_dcerpc_cmd(struct ntvfs_module_context *ntvfs,
600 struct smbsrv_request *req, struct smb_trans2 *trans)
602 struct pipe_state *p;
603 struct ipc_private *private = ntvfs->private_data;
606 /* the fnum is in setup[1] */
607 p = pipe_state_find(private, trans->in.setup[1]);
609 return NT_STATUS_INVALID_HANDLE;
612 trans->out.data = data_blob_talloc(req, NULL, trans->in.max_data);
613 if (!trans->out.data.data) {
614 return NT_STATUS_NO_MEMORY;
617 /* pass the data to the dcerpc server. Note that we don't
618 expect this to fail, and things like NDR faults are not
619 reported at this stage. Those sorts of errors happen in the
620 dcesrv_output stage */
621 status = dcesrv_input(p->dce_conn, &trans->in.data);
622 if (!NT_STATUS_IS_OK(status)) {
627 now ask the dcerpc system for some output. This doesn't yet handle
628 async calls. Again, we only expect NT_STATUS_OK. If the call fails then
629 the error is encoded at the dcerpc level
631 status = dcesrv_output_blob(p->dce_conn, &trans->out.data);
632 if (NT_STATUS_IS_ERR(status)) {
636 trans->out.setup_count = 0;
637 trans->out.setup = NULL;
638 trans->out.params = data_blob(NULL, 0);
644 /* SMBtrans - set named pipe state */
645 static NTSTATUS ipc_set_nm_pipe_state(struct ntvfs_module_context *ntvfs,
646 struct smbsrv_request *req, struct smb_trans2 *trans)
648 struct ipc_private *private = ntvfs->private_data;
649 struct pipe_state *p;
651 /* the fnum is in setup[1] */
652 p = pipe_state_find(private, trans->in.setup[1]);
654 return NT_STATUS_INVALID_HANDLE;
657 if (trans->in.params.length != 2) {
658 return NT_STATUS_INVALID_PARAMETER;
660 p->ipc_state = SVAL(trans->in.params.data, 0);
662 trans->out.setup_count = 0;
663 trans->out.setup = NULL;
664 trans->out.params = data_blob(NULL, 0);
665 trans->out.data = data_blob(NULL, 0);
671 /* SMBtrans - used to provide access to SMB pipes */
672 static NTSTATUS ipc_trans(struct ntvfs_module_context *ntvfs,
673 struct smbsrv_request *req, struct smb_trans2 *trans)
677 if (strequal(trans->in.trans_name, "\\PIPE\\LANMAN"))
678 return ipc_rap_call(req, trans);
680 if (trans->in.setup_count != 2) {
681 return NT_STATUS_INVALID_PARAMETER;
684 switch (trans->in.setup[0]) {
685 case TRANSACT_SETNAMEDPIPEHANDLESTATE:
686 status = ipc_set_nm_pipe_state(ntvfs, req, trans);
688 case TRANSACT_DCERPCCMD:
689 status = ipc_dcerpc_cmd(ntvfs, req, trans);
692 status = NT_STATUS_INVALID_PARAMETER;
702 initialialise the IPC backend, registering ourselves with the ntvfs subsystem
704 NTSTATUS ntvfs_ipc_init(void)
707 struct ntvfs_ops ops;
711 /* fill in the name and type */
712 ops.name = "default";
713 ops.type = NTVFS_IPC;
715 /* fill in all the operations */
716 ops.connect = ipc_connect;
717 ops.disconnect = ipc_disconnect;
718 ops.unlink = ipc_unlink;
719 ops.chkpath = ipc_chkpath;
720 ops.qpathinfo = ipc_qpathinfo;
721 ops.setpathinfo = ipc_setpathinfo;
723 ops.mkdir = ipc_mkdir;
724 ops.rmdir = ipc_rmdir;
725 ops.rename = ipc_rename;
727 ops.ioctl = ipc_ioctl;
729 ops.write = ipc_write;
731 ops.flush = ipc_flush;
732 ops.close = ipc_close;
735 ops.setfileinfo = ipc_setfileinfo;
736 ops.qfileinfo = ipc_qfileinfo;
737 ops.fsinfo = ipc_fsinfo;
739 ops.search_first = ipc_search_first;
740 ops.search_next = ipc_search_next;
741 ops.search_close = ipc_search_close;
742 ops.trans = ipc_trans;
743 ops.logoff = ipc_logoff;
744 ops.async_setup = ipc_async_setup;
746 /* register ourselves with the NTVFS subsystem. */
747 ret = register_backend("ntvfs", &ops);
749 if (!NT_STATUS_IS_OK(ret)) {
750 DEBUG(0,("Failed to register IPC backend!\n"));