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;
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 the next fnum available on this connection
60 static uint16_t find_next_fnum(struct ipc_private *ipc)
65 if (ipc->num_open == 0xFFFF) {
70 ret = ipc->next_fnum++;
72 for (p=ipc->pipe_list; p; p=p->next) {
83 shutdown a single pipe. Called on a close or disconnect
85 static void pipe_shutdown(struct ipc_private *private, struct pipe_state *p)
87 talloc_free(p->dce_conn);
88 DLIST_REMOVE(private->pipe_list, p);
94 find a open pipe give a file descriptor
96 static struct pipe_state *pipe_state_find(struct ipc_private *private, uint16_t fnum)
100 for (p=private->pipe_list; p; p=p->next) {
101 if (p->fnum == fnum) {
111 connect to a share - always works
113 static NTSTATUS ipc_connect(struct ntvfs_module_context *ntvfs,
114 struct smbsrv_request *req, const char *sharename)
116 struct smbsrv_tcon *tcon = req->tcon;
117 struct ipc_private *private;
119 tcon->fs_type = talloc_strdup(tcon, "IPC");
120 tcon->dev_type = talloc_strdup(tcon, "IPC");
122 /* prepare the private state for this connection */
123 private = talloc_p(tcon, struct ipc_private);
125 return NT_STATUS_NO_MEMORY;
127 ntvfs->private_data = private;
129 private->pipe_list = NULL;
130 private->next_fnum = 1;
131 private->num_open = 0;
137 disconnect from a share
139 static NTSTATUS ipc_disconnect(struct ntvfs_module_context *ntvfs,
140 struct smbsrv_tcon *tcon)
142 struct ipc_private *private = ntvfs->private_data;
144 /* close any pipes that are open. Discard any unread data */
145 while (private->pipe_list) {
146 pipe_shutdown(private, private->pipe_list);
155 static NTSTATUS ipc_unlink(struct ntvfs_module_context *ntvfs,
156 struct smbsrv_request *req, struct smb_unlink *unl)
158 return NT_STATUS_ACCESS_DENIED;
163 ioctl interface - we don't do any
165 static NTSTATUS ipc_ioctl(struct ntvfs_module_context *ntvfs,
166 struct smbsrv_request *req, union smb_ioctl *io)
168 return NT_STATUS_ACCESS_DENIED;
172 check if a directory exists
174 static NTSTATUS ipc_chkpath(struct ntvfs_module_context *ntvfs,
175 struct smbsrv_request *req, struct smb_chkpath *cp)
177 return NT_STATUS_ACCESS_DENIED;
181 return info on a pathname
183 static NTSTATUS ipc_qpathinfo(struct ntvfs_module_context *ntvfs,
184 struct smbsrv_request *req, union smb_fileinfo *info)
186 return NT_STATUS_ACCESS_DENIED;
190 set info on a pathname
192 static NTSTATUS ipc_setpathinfo(struct ntvfs_module_context *ntvfs,
193 struct smbsrv_request *req, union smb_setfileinfo *st)
195 return NT_STATUS_ACCESS_DENIED;
201 open a file backend - used for MSRPC pipes
203 static NTSTATUS ipc_open_generic(struct ntvfs_module_context *ntvfs,
204 struct smbsrv_request *req, const char *fname,
205 struct pipe_state **ps)
207 struct pipe_state *p;
209 struct dcesrv_ep_description ep_description;
210 struct auth_session_info *session_info = NULL;
211 struct ipc_private *private = ntvfs->private_data;
213 p = talloc_p(private, struct pipe_state);
215 return NT_STATUS_NO_MEMORY;
218 p->pipe_name = talloc_strdup(p, fname);
221 return NT_STATUS_NO_MEMORY;
224 p->fnum = find_next_fnum(private);
227 return NT_STATUS_TOO_MANY_OPENED_FILES;
230 while (p->pipe_name[0] == '\\') {
233 p->ipc_state = 0x5ff;
236 we're all set, now ask the dcerpc server subsystem to open the
237 endpoint. At this stage the pipe isn't bound, so we don't
238 know what interface the user actually wants, just that they want
239 one of the interfaces attached to this pipe endpoint.
241 TODO: note that we aren't passing any credentials here. We
242 will need to do that once the credentials infrastructure is
246 ep_description.type = ENDPOINT_SMB;
247 ep_description.info.smb_pipe = p->pipe_name;
249 /* tell the RPC layer the session_info */
251 /* The session info is refcount-increased in the
252 dcesrv_endpoint_search_connect() function */
254 session_info = req->session->session_info;
257 status = dcesrv_endpoint_search_connect(req->smb_conn->dcesrv,
261 if (!NT_STATUS_IS_OK(status)) {
268 DLIST_ADD(private->pipe_list, p);
270 p->smbpid = req->smbpid;
271 p->session = req->session;
279 open a file with ntcreatex - used for MSRPC pipes
281 static NTSTATUS ipc_open_ntcreatex(struct ntvfs_module_context *ntvfs,
282 struct smbsrv_request *req, union smb_open *oi)
284 struct pipe_state *p;
287 status = ipc_open_generic(ntvfs, req, oi->ntcreatex.in.fname, &p);
288 if (!NT_STATUS_IS_OK(status)) {
292 ZERO_STRUCT(oi->ntcreatex.out);
293 oi->ntcreatex.out.fnum = p->fnum;
294 oi->ntcreatex.out.ipc_state = p->ipc_state;
300 open a file with openx - used for MSRPC pipes
302 static NTSTATUS ipc_open_openx(struct ntvfs_module_context *ntvfs,
303 struct smbsrv_request *req, union smb_open *oi)
305 struct pipe_state *p;
307 const char *fname = oi->openx.in.fname;
309 if (strncasecmp(fname, "PIPE\\", 5) != 0) {
310 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
315 status = ipc_open_generic(ntvfs, req, fname, &p);
316 if (!NT_STATUS_IS_OK(status)) {
320 ZERO_STRUCT(oi->openx.out);
321 oi->openx.out.fnum = p->fnum;
322 oi->openx.out.ftype = 2;
323 oi->openx.out.devstate = p->ipc_state;
329 open a file - used for MSRPC pipes
331 static NTSTATUS ipc_open(struct ntvfs_module_context *ntvfs,
332 struct smbsrv_request *req, union smb_open *oi)
336 switch (oi->generic.level) {
337 case RAW_OPEN_NTCREATEX:
338 status = ipc_open_ntcreatex(ntvfs, req, oi);
341 status = ipc_open_openx(ntvfs, req, oi);
344 status = NT_STATUS_NOT_SUPPORTED;
354 static NTSTATUS ipc_mkdir(struct ntvfs_module_context *ntvfs,
355 struct smbsrv_request *req, union smb_mkdir *md)
357 return NT_STATUS_ACCESS_DENIED;
363 static NTSTATUS ipc_rmdir(struct ntvfs_module_context *ntvfs,
364 struct smbsrv_request *req, struct smb_rmdir *rd)
366 return NT_STATUS_ACCESS_DENIED;
370 rename a set of files
372 static NTSTATUS ipc_rename(struct ntvfs_module_context *ntvfs,
373 struct smbsrv_request *req, union smb_rename *ren)
375 return NT_STATUS_ACCESS_DENIED;
381 static NTSTATUS ipc_copy(struct ntvfs_module_context *ntvfs,
382 struct smbsrv_request *req, struct smb_copy *cp)
384 return NT_STATUS_ACCESS_DENIED;
390 static NTSTATUS ipc_read(struct ntvfs_module_context *ntvfs,
391 struct smbsrv_request *req, union smb_read *rd)
393 struct ipc_private *private = ntvfs->private_data;
396 struct pipe_state *p;
399 switch (rd->generic.level) {
401 fnum = rd->read.in.fnum;
402 data.length = rd->read.in.count;
403 data.data = rd->read.out.data;
406 fnum = rd->readx.in.fnum;
407 data.length = rd->readx.in.maxcnt;
408 data.data = rd->readx.out.data;
411 return NT_STATUS_NOT_SUPPORTED;
414 p = pipe_state_find(private, fnum);
416 return NT_STATUS_INVALID_HANDLE;
419 status = dcesrv_output_blob(p->dce_conn, &data);
420 if (NT_STATUS_IS_ERR(status)) {
424 switch (rd->generic.level) {
426 rd->read.out.nread = data.length;
429 rd->readx.out.remaining = 0;
430 rd->readx.out.compaction_mode = 0;
431 rd->readx.out.nread = data.length;
434 return NT_STATUS_NOT_SUPPORTED;
443 static NTSTATUS ipc_write(struct ntvfs_module_context *ntvfs,
444 struct smbsrv_request *req, union smb_write *wr)
446 struct ipc_private *private = ntvfs->private_data;
449 struct pipe_state *p;
452 switch (wr->generic.level) {
453 case RAW_WRITE_WRITE:
454 fnum = wr->write.in.fnum;
455 data.data = discard_const_p(void, wr->write.in.data);
456 data.length = wr->write.in.count;
459 case RAW_WRITE_WRITEX:
460 fnum = wr->writex.in.fnum;
461 data.data = discard_const_p(void, wr->writex.in.data);
462 data.length = wr->writex.in.count;
466 return NT_STATUS_NOT_SUPPORTED;
469 p = pipe_state_find(private, fnum);
471 return NT_STATUS_INVALID_HANDLE;
474 status = dcesrv_input(p->dce_conn, &data);
475 if (!NT_STATUS_IS_OK(status)) {
479 switch (wr->generic.level) {
480 case RAW_WRITE_WRITE:
481 wr->write.out.nwritten = data.length;
483 case RAW_WRITE_WRITEX:
484 wr->writex.out.nwritten = data.length;
485 wr->writex.out.remaining = 0;
488 return NT_STATUS_NOT_SUPPORTED;
497 static NTSTATUS ipc_seek(struct ntvfs_module_context *ntvfs,
498 struct smbsrv_request *req, struct smb_seek *io)
500 return NT_STATUS_ACCESS_DENIED;
506 static NTSTATUS ipc_flush(struct ntvfs_module_context *ntvfs,
507 struct smbsrv_request *req, struct smb_flush *io)
509 return NT_STATUS_ACCESS_DENIED;
515 static NTSTATUS ipc_close(struct ntvfs_module_context *ntvfs,
516 struct smbsrv_request *req, union smb_close *io)
518 struct ipc_private *private = ntvfs->private_data;
519 struct pipe_state *p;
521 if (io->generic.level != RAW_CLOSE_CLOSE) {
522 return NT_STATUS_ACCESS_DENIED;
525 p = pipe_state_find(private, io->close.in.fnum);
527 return NT_STATUS_INVALID_HANDLE;
530 pipe_shutdown(private, p);
539 static NTSTATUS ipc_exit(struct ntvfs_module_context *ntvfs,
540 struct smbsrv_request *req)
542 struct ipc_private *private = ntvfs->private_data;
543 struct pipe_state *p, *next;
545 for (p=private->pipe_list; p; p=next) {
547 if (p->smbpid == req->smbpid) {
548 pipe_shutdown(private, p);
556 logoff - closing files open by the user
558 static NTSTATUS ipc_logoff(struct ntvfs_module_context *ntvfs,
559 struct smbsrv_request *req)
561 struct ipc_private *private = ntvfs->private_data;
562 struct pipe_state *p, *next;
564 for (p=private->pipe_list; p; p=next) {
566 if (p->session == req->session) {
567 pipe_shutdown(private, p);
577 static NTSTATUS ipc_lock(struct ntvfs_module_context *ntvfs,
578 struct smbsrv_request *req, union smb_lock *lck)
580 return NT_STATUS_ACCESS_DENIED;
584 set info on a open file
586 static NTSTATUS ipc_setfileinfo(struct ntvfs_module_context *ntvfs,
587 struct smbsrv_request *req, union smb_setfileinfo *info)
589 return NT_STATUS_ACCESS_DENIED;
593 query info on a open file
595 static NTSTATUS ipc_qfileinfo(struct ntvfs_module_context *ntvfs,
596 struct smbsrv_request *req, union smb_fileinfo *info)
598 return NT_STATUS_ACCESS_DENIED;
603 return filesystem info
605 static NTSTATUS ipc_fsinfo(struct ntvfs_module_context *ntvfs,
606 struct smbsrv_request *req, union smb_fsinfo *fs)
608 return NT_STATUS_ACCESS_DENIED;
612 return print queue info
614 static NTSTATUS ipc_lpq(struct ntvfs_module_context *ntvfs,
615 struct smbsrv_request *req, union smb_lpq *lpq)
617 return NT_STATUS_ACCESS_DENIED;
621 list files in a directory matching a wildcard pattern
623 static NTSTATUS ipc_search_first(struct ntvfs_module_context *ntvfs,
624 struct smbsrv_request *req, union smb_search_first *io,
625 void *search_private,
626 BOOL (*callback)(void *, union smb_search_data *))
628 return NT_STATUS_ACCESS_DENIED;
632 continue listing files in a directory
634 static NTSTATUS ipc_search_next(struct ntvfs_module_context *ntvfs,
635 struct smbsrv_request *req, union smb_search_next *io,
636 void *search_private,
637 BOOL (*callback)(void *, union smb_search_data *))
639 return NT_STATUS_ACCESS_DENIED;
643 end listing files in a directory
645 static NTSTATUS ipc_search_close(struct ntvfs_module_context *ntvfs,
646 struct smbsrv_request *req, union smb_search_close *io)
648 return NT_STATUS_ACCESS_DENIED;
652 /* SMBtrans - handle a DCERPC command */
653 static NTSTATUS ipc_dcerpc_cmd(struct ntvfs_module_context *ntvfs,
654 struct smbsrv_request *req, struct smb_trans2 *trans)
656 struct pipe_state *p;
657 struct ipc_private *private = ntvfs->private_data;
660 /* the fnum is in setup[1] */
661 p = pipe_state_find(private, trans->in.setup[1]);
663 return NT_STATUS_INVALID_HANDLE;
666 trans->out.data = data_blob_talloc(req, NULL, trans->in.max_data);
667 if (!trans->out.data.data) {
668 return NT_STATUS_NO_MEMORY;
671 /* pass the data to the dcerpc server. Note that we don't
672 expect this to fail, and things like NDR faults are not
673 reported at this stage. Those sorts of errors happen in the
674 dcesrv_output stage */
675 status = dcesrv_input(p->dce_conn, &trans->in.data);
676 if (!NT_STATUS_IS_OK(status)) {
681 now ask the dcerpc system for some output. This doesn't yet handle
682 async calls. Again, we only expect NT_STATUS_OK. If the call fails then
683 the error is encoded at the dcerpc level
685 status = dcesrv_output_blob(p->dce_conn, &trans->out.data);
686 if (NT_STATUS_IS_ERR(status)) {
690 trans->out.setup_count = 0;
691 trans->out.setup = NULL;
692 trans->out.params = data_blob(NULL, 0);
698 /* SMBtrans - set named pipe state */
699 static NTSTATUS ipc_set_nm_pipe_state(struct ntvfs_module_context *ntvfs,
700 struct smbsrv_request *req, struct smb_trans2 *trans)
702 struct ipc_private *private = ntvfs->private_data;
703 struct pipe_state *p;
705 /* the fnum is in setup[1] */
706 p = pipe_state_find(private, trans->in.setup[1]);
708 return NT_STATUS_INVALID_HANDLE;
711 if (trans->in.params.length != 2) {
712 return NT_STATUS_INVALID_PARAMETER;
714 p->ipc_state = SVAL(trans->in.params.data, 0);
716 trans->out.setup_count = 0;
717 trans->out.setup = NULL;
718 trans->out.params = data_blob(NULL, 0);
719 trans->out.data = data_blob(NULL, 0);
725 /* SMBtrans - used to provide access to SMB pipes */
726 static NTSTATUS ipc_trans(struct ntvfs_module_context *ntvfs,
727 struct smbsrv_request *req, struct smb_trans2 *trans)
731 if (strequal(trans->in.trans_name, "\\PIPE\\LANMAN"))
732 return ipc_rap_call(req, trans);
734 if (trans->in.setup_count != 2) {
735 return NT_STATUS_INVALID_PARAMETER;
738 switch (trans->in.setup[0]) {
739 case TRANSACT_SETNAMEDPIPEHANDLESTATE:
740 status = ipc_set_nm_pipe_state(ntvfs, req, trans);
742 case TRANSACT_DCERPCCMD:
743 status = ipc_dcerpc_cmd(ntvfs, req, trans);
746 status = NT_STATUS_INVALID_PARAMETER;
756 initialialise the IPC backend, registering ourselves with the ntvfs subsystem
758 NTSTATUS ntvfs_ipc_init(void)
761 struct ntvfs_ops ops;
765 /* fill in the name and type */
766 ops.name = "default";
767 ops.type = NTVFS_IPC;
769 /* fill in all the operations */
770 ops.connect = ipc_connect;
771 ops.disconnect = ipc_disconnect;
772 ops.unlink = ipc_unlink;
773 ops.chkpath = ipc_chkpath;
774 ops.qpathinfo = ipc_qpathinfo;
775 ops.setpathinfo = ipc_setpathinfo;
777 ops.mkdir = ipc_mkdir;
778 ops.rmdir = ipc_rmdir;
779 ops.rename = ipc_rename;
781 ops.ioctl = ipc_ioctl;
783 ops.write = ipc_write;
785 ops.flush = ipc_flush;
786 ops.close = ipc_close;
789 ops.setfileinfo = ipc_setfileinfo;
790 ops.qfileinfo = ipc_qfileinfo;
791 ops.fsinfo = ipc_fsinfo;
793 ops.search_first = ipc_search_first;
794 ops.search_next = ipc_search_next;
795 ops.search_close = ipc_search_close;
796 ops.trans = ipc_trans;
797 ops.logoff = ipc_logoff;
799 /* register ourselves with the NTVFS subsystem. */
800 ret = register_backend("ntvfs", &ops);
802 if (!NT_STATUS_IS_OK(ret)) {
803 DEBUG(0,("Failed to register IPC backend!\n"));