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
36 /* a list of open pipes */
38 struct pipe_state *next, *prev;
39 struct ipc_private *private;
40 const char *pipe_name;
42 struct dcesrv_connection *dce_conn;
44 /* we need to remember the session it was opened on,
45 as it is illegal to operate on someone elses fnum */
46 struct smbsrv_session *session;
48 /* we need to remember the client pid that
49 opened the file so SMBexit works */
57 find a open pipe give a file descriptor
59 static struct pipe_state *pipe_state_find(struct ipc_private *private, uint16_t fnum)
61 return idr_find(private->idtree_fnum, fnum);
66 connect to a share - always works
68 static NTSTATUS ipc_connect(struct ntvfs_module_context *ntvfs,
69 struct smbsrv_request *req, const char *sharename)
71 struct smbsrv_tcon *tcon = req->tcon;
72 struct ipc_private *private;
74 tcon->fs_type = talloc_strdup(tcon, "IPC");
75 tcon->dev_type = talloc_strdup(tcon, "IPC");
77 /* prepare the private state for this connection */
78 private = talloc_p(tcon, struct ipc_private);
80 return NT_STATUS_NO_MEMORY;
82 ntvfs->private_data = private;
84 private->pipe_list = NULL;
86 private->idtree_fnum = idr_init(private);
87 if (private->idtree_fnum == NULL) {
88 return NT_STATUS_NO_MEMORY;
95 disconnect from a share
97 static NTSTATUS ipc_disconnect(struct ntvfs_module_context *ntvfs,
98 struct smbsrv_tcon *tcon)
100 struct ipc_private *private = ntvfs->private_data;
102 /* close any pipes that are open. Discard any unread data */
103 while (private->pipe_list) {
104 talloc_free(private->pipe_list);
113 static NTSTATUS ipc_unlink(struct ntvfs_module_context *ntvfs,
114 struct smbsrv_request *req, struct smb_unlink *unl)
116 return NT_STATUS_ACCESS_DENIED;
121 ioctl interface - we don't do any
123 static NTSTATUS ipc_ioctl(struct ntvfs_module_context *ntvfs,
124 struct smbsrv_request *req, union smb_ioctl *io)
126 return NT_STATUS_ACCESS_DENIED;
130 check if a directory exists
132 static NTSTATUS ipc_chkpath(struct ntvfs_module_context *ntvfs,
133 struct smbsrv_request *req, struct smb_chkpath *cp)
135 return NT_STATUS_ACCESS_DENIED;
139 return info on a pathname
141 static NTSTATUS ipc_qpathinfo(struct ntvfs_module_context *ntvfs,
142 struct smbsrv_request *req, union smb_fileinfo *info)
144 return NT_STATUS_ACCESS_DENIED;
148 set info on a pathname
150 static NTSTATUS ipc_setpathinfo(struct ntvfs_module_context *ntvfs,
151 struct smbsrv_request *req, union smb_setfileinfo *st)
153 return NT_STATUS_ACCESS_DENIED;
158 destroy a open pipe structure
160 static int ipc_fd_destructor(void *ptr)
162 struct pipe_state *p = ptr;
163 idr_remove(p->private->idtree_fnum, p->fnum);
164 DLIST_REMOVE(p->private->pipe_list, p);
165 talloc_free(p->dce_conn);
171 open a file backend - used for MSRPC pipes
173 static NTSTATUS ipc_open_generic(struct ntvfs_module_context *ntvfs,
174 struct smbsrv_request *req, const char *fname,
175 struct pipe_state **ps)
177 struct pipe_state *p;
179 struct dcesrv_ep_description ep_description;
180 struct auth_session_info *session_info = NULL;
181 struct ipc_private *private = ntvfs->private_data;
184 p = talloc_p(req, struct pipe_state);
186 return NT_STATUS_NO_MEMORY;
189 while (fname[0] == '\\') fname++;
191 p->pipe_name = talloc_asprintf(p, "\\pipe\\%s", fname);
193 return NT_STATUS_NO_MEMORY;
196 fnum = idr_get_new(private->idtree_fnum, p, UINT16_MAX);
198 return NT_STATUS_TOO_MANY_OPENED_FILES;
202 p->ipc_state = 0x5ff;
205 we're all set, now ask the dcerpc server subsystem to open the
206 endpoint. At this stage the pipe isn't bound, so we don't
207 know what interface the user actually wants, just that they want
208 one of the interfaces attached to this pipe endpoint.
210 TODO: note that we aren't passing any credentials here. We
211 will need to do that once the credentials infrastructure is
214 ep_description.type = NCACN_NP;
215 ep_description.info.smb_pipe = p->pipe_name;
217 /* tell the RPC layer the session_info */
219 /* The session info is refcount-increased in the
220 dcesrv_endpoint_search_connect() function */
221 session_info = req->session->session_info;
224 status = dcesrv_endpoint_search_connect(req->smb_conn->dcesrv,
228 if (!NT_STATUS_IS_OK(status)) {
229 idr_remove(private->idtree_fnum, p->fnum);
233 DLIST_ADD(private->pipe_list, p);
235 p->smbpid = req->smbpid;
236 p->session = req->session;
237 p->private = private;
241 talloc_steal(private, p);
243 talloc_set_destructor(p, ipc_fd_destructor);
249 open a file with ntcreatex - used for MSRPC pipes
251 static NTSTATUS ipc_open_ntcreatex(struct ntvfs_module_context *ntvfs,
252 struct smbsrv_request *req, union smb_open *oi)
254 struct pipe_state *p;
257 status = ipc_open_generic(ntvfs, req, oi->ntcreatex.in.fname, &p);
258 if (!NT_STATUS_IS_OK(status)) {
262 ZERO_STRUCT(oi->ntcreatex.out);
263 oi->ntcreatex.out.fnum = p->fnum;
264 oi->ntcreatex.out.ipc_state = p->ipc_state;
270 open a file with openx - used for MSRPC pipes
272 static NTSTATUS ipc_open_openx(struct ntvfs_module_context *ntvfs,
273 struct smbsrv_request *req, union smb_open *oi)
275 struct pipe_state *p;
277 const char *fname = oi->openx.in.fname;
279 status = ipc_open_generic(ntvfs, req, fname, &p);
280 if (!NT_STATUS_IS_OK(status)) {
284 ZERO_STRUCT(oi->openx.out);
285 oi->openx.out.fnum = p->fnum;
286 oi->openx.out.ftype = 2;
287 oi->openx.out.devstate = p->ipc_state;
293 open a file - used for MSRPC pipes
295 static NTSTATUS ipc_open(struct ntvfs_module_context *ntvfs,
296 struct smbsrv_request *req, union smb_open *oi)
300 switch (oi->generic.level) {
301 case RAW_OPEN_NTCREATEX:
302 status = ipc_open_ntcreatex(ntvfs, req, oi);
305 status = ipc_open_openx(ntvfs, req, oi);
308 status = NT_STATUS_NOT_SUPPORTED;
318 static NTSTATUS ipc_mkdir(struct ntvfs_module_context *ntvfs,
319 struct smbsrv_request *req, union smb_mkdir *md)
321 return NT_STATUS_ACCESS_DENIED;
327 static NTSTATUS ipc_rmdir(struct ntvfs_module_context *ntvfs,
328 struct smbsrv_request *req, struct smb_rmdir *rd)
330 return NT_STATUS_ACCESS_DENIED;
334 rename a set of files
336 static NTSTATUS ipc_rename(struct ntvfs_module_context *ntvfs,
337 struct smbsrv_request *req, union smb_rename *ren)
339 return NT_STATUS_ACCESS_DENIED;
345 static NTSTATUS ipc_copy(struct ntvfs_module_context *ntvfs,
346 struct smbsrv_request *req, struct smb_copy *cp)
348 return NT_STATUS_ACCESS_DENIED;
354 static NTSTATUS ipc_read(struct ntvfs_module_context *ntvfs,
355 struct smbsrv_request *req, union smb_read *rd)
357 struct ipc_private *private = ntvfs->private_data;
360 struct pipe_state *p;
363 if (rd->generic.level != RAW_READ_GENERIC) {
364 return ntvfs_map_read(req, rd, ntvfs);
367 fnum = rd->readx.in.fnum;
368 data.length = rd->readx.in.maxcnt;
369 data.data = rd->readx.out.data;
371 p = pipe_state_find(private, fnum);
373 return NT_STATUS_INVALID_HANDLE;
376 status = dcesrv_output_blob(p->dce_conn, &data);
377 if (NT_STATUS_IS_ERR(status)) {
381 rd->readx.out.remaining = 0;
382 rd->readx.out.compaction_mode = 0;
383 rd->readx.out.nread = data.length;
391 static NTSTATUS ipc_write(struct ntvfs_module_context *ntvfs,
392 struct smbsrv_request *req, union smb_write *wr)
394 struct ipc_private *private = ntvfs->private_data;
397 struct pipe_state *p;
400 if (wr->generic.level != RAW_WRITE_GENERIC) {
401 return ntvfs_map_write(req, wr, ntvfs);
404 fnum = wr->writex.in.fnum;
405 data.data = discard_const_p(void, wr->writex.in.data);
406 data.length = wr->writex.in.count;
408 p = pipe_state_find(private, fnum);
410 return NT_STATUS_INVALID_HANDLE;
413 status = dcesrv_input(p->dce_conn, &data);
414 if (!NT_STATUS_IS_OK(status)) {
418 wr->writex.out.nwritten = data.length;
419 wr->writex.out.remaining = 0;
427 static NTSTATUS ipc_seek(struct ntvfs_module_context *ntvfs,
428 struct smbsrv_request *req, struct smb_seek *io)
430 return NT_STATUS_ACCESS_DENIED;
436 static NTSTATUS ipc_flush(struct ntvfs_module_context *ntvfs,
437 struct smbsrv_request *req, struct smb_flush *io)
439 return NT_STATUS_ACCESS_DENIED;
445 static NTSTATUS ipc_close(struct ntvfs_module_context *ntvfs,
446 struct smbsrv_request *req, union smb_close *io)
448 struct ipc_private *private = ntvfs->private_data;
449 struct pipe_state *p;
451 if (io->generic.level != RAW_CLOSE_CLOSE) {
452 return ntvfs_map_close(req, io, ntvfs);
455 p = pipe_state_find(private, io->close.in.fnum);
457 return NT_STATUS_INVALID_HANDLE;
468 static NTSTATUS ipc_exit(struct ntvfs_module_context *ntvfs,
469 struct smbsrv_request *req)
471 struct ipc_private *private = ntvfs->private_data;
472 struct pipe_state *p, *next;
474 for (p=private->pipe_list; p; p=next) {
476 if (p->smbpid == req->smbpid) {
485 logoff - closing files open by the user
487 static NTSTATUS ipc_logoff(struct ntvfs_module_context *ntvfs,
488 struct smbsrv_request *req)
490 struct ipc_private *private = ntvfs->private_data;
491 struct pipe_state *p, *next;
493 for (p=private->pipe_list; p; p=next) {
495 if (p->session == req->session) {
504 setup for an async call
506 static NTSTATUS ipc_async_setup(struct ntvfs_module_context *ntvfs,
507 struct smbsrv_request *req,
516 static NTSTATUS ipc_lock(struct ntvfs_module_context *ntvfs,
517 struct smbsrv_request *req, union smb_lock *lck)
519 return NT_STATUS_ACCESS_DENIED;
523 set info on a open file
525 static NTSTATUS ipc_setfileinfo(struct ntvfs_module_context *ntvfs,
526 struct smbsrv_request *req, union smb_setfileinfo *info)
528 return NT_STATUS_ACCESS_DENIED;
532 query info on a open file
534 static NTSTATUS ipc_qfileinfo(struct ntvfs_module_context *ntvfs,
535 struct smbsrv_request *req, union smb_fileinfo *info)
537 return NT_STATUS_ACCESS_DENIED;
542 return filesystem info
544 static NTSTATUS ipc_fsinfo(struct ntvfs_module_context *ntvfs,
545 struct smbsrv_request *req, union smb_fsinfo *fs)
547 return NT_STATUS_ACCESS_DENIED;
551 return print queue info
553 static NTSTATUS ipc_lpq(struct ntvfs_module_context *ntvfs,
554 struct smbsrv_request *req, union smb_lpq *lpq)
556 return NT_STATUS_ACCESS_DENIED;
560 list files in a directory matching a wildcard pattern
562 static NTSTATUS ipc_search_first(struct ntvfs_module_context *ntvfs,
563 struct smbsrv_request *req, union smb_search_first *io,
564 void *search_private,
565 BOOL (*callback)(void *, union smb_search_data *))
567 return NT_STATUS_ACCESS_DENIED;
571 continue listing files in a directory
573 static NTSTATUS ipc_search_next(struct ntvfs_module_context *ntvfs,
574 struct smbsrv_request *req, union smb_search_next *io,
575 void *search_private,
576 BOOL (*callback)(void *, union smb_search_data *))
578 return NT_STATUS_ACCESS_DENIED;
582 end listing files in a directory
584 static NTSTATUS ipc_search_close(struct ntvfs_module_context *ntvfs,
585 struct smbsrv_request *req, union smb_search_close *io)
587 return NT_STATUS_ACCESS_DENIED;
591 /* SMBtrans - handle a DCERPC command */
592 static NTSTATUS ipc_dcerpc_cmd(struct ntvfs_module_context *ntvfs,
593 struct smbsrv_request *req, struct smb_trans2 *trans)
595 struct pipe_state *p;
596 struct ipc_private *private = ntvfs->private_data;
599 /* the fnum is in setup[1] */
600 p = pipe_state_find(private, trans->in.setup[1]);
602 return NT_STATUS_INVALID_HANDLE;
605 trans->out.data = data_blob_talloc(req, NULL, trans->in.max_data);
606 if (!trans->out.data.data) {
607 return NT_STATUS_NO_MEMORY;
610 /* pass the data to the dcerpc server. Note that we don't
611 expect this to fail, and things like NDR faults are not
612 reported at this stage. Those sorts of errors happen in the
613 dcesrv_output stage */
614 status = dcesrv_input(p->dce_conn, &trans->in.data);
615 if (!NT_STATUS_IS_OK(status)) {
620 now ask the dcerpc system for some output. This doesn't yet handle
621 async calls. Again, we only expect NT_STATUS_OK. If the call fails then
622 the error is encoded at the dcerpc level
624 status = dcesrv_output_blob(p->dce_conn, &trans->out.data);
625 if (NT_STATUS_IS_ERR(status)) {
629 trans->out.setup_count = 0;
630 trans->out.setup = NULL;
631 trans->out.params = data_blob(NULL, 0);
637 /* SMBtrans - set named pipe state */
638 static NTSTATUS ipc_set_nm_pipe_state(struct ntvfs_module_context *ntvfs,
639 struct smbsrv_request *req, struct smb_trans2 *trans)
641 struct ipc_private *private = ntvfs->private_data;
642 struct pipe_state *p;
644 /* the fnum is in setup[1] */
645 p = pipe_state_find(private, trans->in.setup[1]);
647 return NT_STATUS_INVALID_HANDLE;
650 if (trans->in.params.length != 2) {
651 return NT_STATUS_INVALID_PARAMETER;
653 p->ipc_state = SVAL(trans->in.params.data, 0);
655 trans->out.setup_count = 0;
656 trans->out.setup = NULL;
657 trans->out.params = data_blob(NULL, 0);
658 trans->out.data = data_blob(NULL, 0);
664 /* SMBtrans - used to provide access to SMB pipes */
665 static NTSTATUS ipc_trans(struct ntvfs_module_context *ntvfs,
666 struct smbsrv_request *req, struct smb_trans2 *trans)
670 if (strequal(trans->in.trans_name, "\\PIPE\\LANMAN"))
671 return ipc_rap_call(req, trans);
673 if (trans->in.setup_count != 2) {
674 return NT_STATUS_INVALID_PARAMETER;
677 switch (trans->in.setup[0]) {
678 case TRANSACT_SETNAMEDPIPEHANDLESTATE:
679 status = ipc_set_nm_pipe_state(ntvfs, req, trans);
681 case TRANSACT_DCERPCCMD:
682 status = ipc_dcerpc_cmd(ntvfs, req, trans);
685 status = NT_STATUS_INVALID_PARAMETER;
695 initialialise the IPC backend, registering ourselves with the ntvfs subsystem
697 NTSTATUS ntvfs_ipc_init(void)
700 struct ntvfs_ops ops;
704 /* fill in the name and type */
705 ops.name = "default";
706 ops.type = NTVFS_IPC;
708 /* fill in all the operations */
709 ops.connect = ipc_connect;
710 ops.disconnect = ipc_disconnect;
711 ops.unlink = ipc_unlink;
712 ops.chkpath = ipc_chkpath;
713 ops.qpathinfo = ipc_qpathinfo;
714 ops.setpathinfo = ipc_setpathinfo;
716 ops.mkdir = ipc_mkdir;
717 ops.rmdir = ipc_rmdir;
718 ops.rename = ipc_rename;
720 ops.ioctl = ipc_ioctl;
722 ops.write = ipc_write;
724 ops.flush = ipc_flush;
725 ops.close = ipc_close;
728 ops.setfileinfo = ipc_setfileinfo;
729 ops.qfileinfo = ipc_qfileinfo;
730 ops.fsinfo = ipc_fsinfo;
732 ops.search_first = ipc_search_first;
733 ops.search_next = ipc_search_next;
734 ops.search_close = ipc_search_close;
735 ops.trans = ipc_trans;
736 ops.logoff = ipc_logoff;
737 ops.async_setup = ipc_async_setup;
739 /* register ourselves with the NTVFS subsystem. */
740 ret = register_backend("ntvfs", &ops);
742 if (!NT_STATUS_IS_OK(ret)) {
743 DEBUG(0,("Failed to register IPC backend!\n"));