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 smbsrv_request *req, const char *sharename, int depth)
110 struct smbsrv_tcon *tcon = req->tcon;
111 struct ipc_private *private;
113 tcon->fs_type = talloc_strdup(tcon, "IPC");
114 tcon->dev_type = talloc_strdup(tcon, "IPC");
116 /* prepare the private state for this connection */
117 private = talloc_p(tcon, struct ipc_private);
119 return NT_STATUS_NO_MEMORY;
121 ntvfs_set_private(tcon, depth, 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 smbsrv_tcon *tcon, int depth)
135 struct ipc_private *private = tcon->ntvfs_private_list[depth];
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 smbsrv_request *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 smbsrv_request *req, union smb_ioctl *io)
159 return NT_STATUS_ACCESS_DENIED;
163 check if a directory exists
165 static NTSTATUS ipc_chkpath(struct smbsrv_request *req, struct smb_chkpath *cp)
167 return NT_STATUS_ACCESS_DENIED;
171 return info on a pathname
173 static NTSTATUS ipc_qpathinfo(struct smbsrv_request *req, union smb_fileinfo *info)
175 return NT_STATUS_ACCESS_DENIED;
179 set info on a pathname
181 static NTSTATUS ipc_setpathinfo(struct smbsrv_request *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 smbsrv_request *req, const char *fname,
192 struct pipe_state **ps)
194 struct pipe_state *p;
197 struct dcesrv_ep_description ep_description;
198 struct auth_session_info *session_info = NULL;
199 NTVFS_GET_PRIVATE(ipc_private, private, req);
201 mem_ctx = talloc_init("ipc_open '%s'", fname);
203 return NT_STATUS_NO_MEMORY;
206 p = talloc(mem_ctx, sizeof(struct pipe_state));
208 talloc_destroy(mem_ctx);
209 return NT_STATUS_NO_MEMORY;
211 p->mem_ctx = mem_ctx;
213 p->pipe_name = talloc_strdup(mem_ctx, fname);
215 talloc_destroy(mem_ctx);
216 return NT_STATUS_NO_MEMORY;
219 p->fnum = find_next_fnum(private);
221 talloc_destroy(mem_ctx);
222 return NT_STATUS_TOO_MANY_OPENED_FILES;
225 while (p->pipe_name[0] == '\\') {
228 p->ipc_state = 0x5ff;
231 we're all set, now ask the dcerpc server subsystem to open the
232 endpoint. At this stage the pipe isn't bound, so we don't
233 know what interface the user actually wants, just that they want
234 one of the interfaces attached to this pipe endpoint.
236 TODO: note that we aren't passing any credentials here. We
237 will need to do that once the credentials infrastructure is
241 ep_description.type = ENDPOINT_SMB;
242 ep_description.info.smb_pipe = p->pipe_name;
244 /* tell the RPC layer the session_info */
246 /* The session info is refcount-increased in the
247 dcesrv_endpoint_search_connect() function */
249 session_info = req->session->session_info;
252 status = dcesrv_endpoint_search_connect(req->smb_conn->dcesrv,
256 if (!NT_STATUS_IS_OK(status)) {
257 talloc_destroy(mem_ctx);
263 DLIST_ADD(private->pipe_list, p);
271 open a file with ntcreatex - used for MSRPC pipes
273 static NTSTATUS ipc_open_ntcreatex(struct smbsrv_request *req, union smb_open *oi)
275 struct pipe_state *p;
278 status = ipc_open_generic(req, oi->ntcreatex.in.fname, &p);
279 if (!NT_STATUS_IS_OK(status)) {
283 ZERO_STRUCT(oi->ntcreatex.out);
284 oi->ntcreatex.out.fnum = p->fnum;
285 oi->ntcreatex.out.ipc_state = p->ipc_state;
291 open a file with openx - used for MSRPC pipes
293 static NTSTATUS ipc_open_openx(struct smbsrv_request *req, union smb_open *oi)
295 struct pipe_state *p;
297 const char *fname = oi->openx.in.fname;
299 if (strncasecmp(fname, "PIPE\\", 5) != 0) {
300 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
305 status = ipc_open_generic(req, fname, &p);
306 if (!NT_STATUS_IS_OK(status)) {
310 ZERO_STRUCT(oi->openx.out);
311 oi->openx.out.fnum = p->fnum;
312 oi->openx.out.ftype = 2;
313 oi->openx.out.devstate = p->ipc_state;
319 open a file - used for MSRPC pipes
321 static NTSTATUS ipc_open(struct smbsrv_request *req, union smb_open *oi)
325 switch (oi->generic.level) {
326 case RAW_OPEN_NTCREATEX:
327 status = ipc_open_ntcreatex(req, oi);
330 status = ipc_open_openx(req, oi);
333 status = NT_STATUS_NOT_SUPPORTED;
343 static NTSTATUS ipc_mkdir(struct smbsrv_request *req, union smb_mkdir *md)
345 return NT_STATUS_ACCESS_DENIED;
351 static NTSTATUS ipc_rmdir(struct smbsrv_request *req, struct smb_rmdir *rd)
353 return NT_STATUS_ACCESS_DENIED;
357 rename a set of files
359 static NTSTATUS ipc_rename(struct smbsrv_request *req, union smb_rename *ren)
361 return NT_STATUS_ACCESS_DENIED;
367 static NTSTATUS ipc_copy(struct smbsrv_request *req, struct smb_copy *cp)
369 return NT_STATUS_ACCESS_DENIED;
375 static NTSTATUS ipc_read(struct smbsrv_request *req, union smb_read *rd)
377 NTVFS_GET_PRIVATE(ipc_private, private, req);
380 struct pipe_state *p;
383 switch (rd->generic.level) {
385 fnum = rd->read.in.fnum;
386 data.length = rd->read.in.count;
387 data.data = rd->read.out.data;
390 fnum = rd->readx.in.fnum;
391 data.length = rd->readx.in.maxcnt;
392 data.data = rd->readx.out.data;
395 return NT_STATUS_NOT_SUPPORTED;
398 p = pipe_state_find(private, fnum);
400 return NT_STATUS_INVALID_HANDLE;
403 status = dcesrv_output_blob(p->dce_conn, &data);
404 if (NT_STATUS_IS_ERR(status)) {
408 switch (rd->generic.level) {
410 rd->read.out.nread = data.length;
413 rd->readx.out.remaining = 0;
414 rd->readx.out.compaction_mode = 0;
415 rd->readx.out.nread = data.length;
418 return NT_STATUS_NOT_SUPPORTED;
427 static NTSTATUS ipc_write(struct smbsrv_request *req, union smb_write *wr)
429 NTVFS_GET_PRIVATE(ipc_private, private, req);
432 struct pipe_state *p;
435 switch (wr->generic.level) {
436 case RAW_WRITE_WRITE:
437 fnum = wr->write.in.fnum;
438 data.data = wr->write.in.data;
439 data.length = wr->write.in.count;
442 case RAW_WRITE_WRITEX:
443 fnum = wr->writex.in.fnum;
444 data.data = wr->writex.in.data;
445 data.length = wr->writex.in.count;
449 return NT_STATUS_NOT_SUPPORTED;
452 p = pipe_state_find(private, fnum);
454 return NT_STATUS_INVALID_HANDLE;
457 status = dcesrv_input(p->dce_conn, &data);
458 if (!NT_STATUS_IS_OK(status)) {
462 switch (wr->generic.level) {
463 case RAW_WRITE_WRITE:
464 wr->write.out.nwritten = data.length;
466 case RAW_WRITE_WRITEX:
467 wr->writex.out.nwritten = data.length;
468 wr->writex.out.remaining = 0;
471 return NT_STATUS_NOT_SUPPORTED;
480 static NTSTATUS ipc_seek(struct smbsrv_request *req, struct smb_seek *io)
482 return NT_STATUS_ACCESS_DENIED;
488 static NTSTATUS ipc_flush(struct smbsrv_request *req, struct smb_flush *io)
490 return NT_STATUS_ACCESS_DENIED;
496 static NTSTATUS ipc_close(struct smbsrv_request *req, union smb_close *io)
498 NTVFS_GET_PRIVATE(ipc_private, private, req);
499 struct pipe_state *p;
501 if (io->generic.level != RAW_CLOSE_CLOSE) {
502 return NT_STATUS_ACCESS_DENIED;
505 p = pipe_state_find(private, io->close.in.fnum);
507 return NT_STATUS_INVALID_HANDLE;
510 pipe_shutdown(private, p);
517 exit - closing files?
519 static NTSTATUS ipc_exit(struct smbsrv_request *req)
521 return NT_STATUS_ACCESS_DENIED;
527 static NTSTATUS ipc_lock(struct smbsrv_request *req, union smb_lock *lck)
529 return NT_STATUS_ACCESS_DENIED;
533 set info on a open file
535 static NTSTATUS ipc_setfileinfo(struct smbsrv_request *req, union smb_setfileinfo *info)
537 return NT_STATUS_ACCESS_DENIED;
541 query info on a open file
543 static NTSTATUS ipc_qfileinfo(struct smbsrv_request *req, union smb_fileinfo *info)
545 return NT_STATUS_ACCESS_DENIED;
550 return filesystem info
552 static NTSTATUS ipc_fsinfo(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 smbsrv_request *req, union smb_lpq *lpq)
562 return NT_STATUS_ACCESS_DENIED;
566 list files in a directory matching a wildcard pattern
568 NTSTATUS ipc_search_first(struct smbsrv_request *req, union smb_search_first *io,
569 void *search_private,
570 BOOL (*callback)(void *, union smb_search_data *))
572 return NT_STATUS_ACCESS_DENIED;
576 continue listing files in a directory
578 NTSTATUS ipc_search_next(struct smbsrv_request *req, union smb_search_next *io,
579 void *search_private,
580 BOOL (*callback)(void *, union smb_search_data *))
582 return NT_STATUS_ACCESS_DENIED;
586 end listing files in a directory
588 NTSTATUS ipc_search_close(struct smbsrv_request *req, union smb_search_close *io)
590 return NT_STATUS_ACCESS_DENIED;
594 /* SMBtrans - handle a DCERPC command */
595 static NTSTATUS ipc_dcerpc_cmd(struct smbsrv_request *req, struct smb_trans2 *trans)
597 struct pipe_state *p;
598 NTVFS_GET_PRIVATE(ipc_private, private, req);
601 /* the fnum is in setup[1] */
602 p = pipe_state_find(private, trans->in.setup[1]);
604 return NT_STATUS_INVALID_HANDLE;
607 trans->out.data = data_blob_talloc(req, NULL, trans->in.max_data);
608 if (!trans->out.data.data) {
609 return NT_STATUS_NO_MEMORY;
612 /* pass the data to the dcerpc server. Note that we don't
613 expect this to fail, and things like NDR faults are not
614 reported at this stage. Those sorts of errors happen in the
615 dcesrv_output stage */
616 status = dcesrv_input(p->dce_conn, &trans->in.data);
617 if (!NT_STATUS_IS_OK(status)) {
622 now ask the dcerpc system for some output. This doesn't yet handle
623 async calls. Again, we only expect NT_STATUS_OK. If the call fails then
624 the error is encoded at the dcerpc level
626 status = dcesrv_output_blob(p->dce_conn, &trans->out.data);
627 if (NT_STATUS_IS_ERR(status)) {
631 trans->out.setup_count = 0;
632 trans->out.setup = NULL;
633 trans->out.params = data_blob(NULL, 0);
639 /* SMBtrans - set named pipe state */
640 static NTSTATUS ipc_set_nm_pipe_state(struct smbsrv_request *req, struct smb_trans2 *trans)
642 NTVFS_GET_PRIVATE(ipc_private, private, req);
643 struct pipe_state *p;
645 /* the fnum is in setup[1] */
646 p = pipe_state_find(private, trans->in.setup[1]);
648 return NT_STATUS_INVALID_HANDLE;
651 if (trans->in.params.length != 2) {
652 return NT_STATUS_INVALID_PARAMETER;
654 p->ipc_state = SVAL(trans->in.params.data, 0);
656 trans->out.setup_count = 0;
657 trans->out.setup = NULL;
658 trans->out.params = data_blob(NULL, 0);
659 trans->out.data = data_blob(NULL, 0);
665 /* SMBtrans - used to provide access to SMB pipes */
666 static NTSTATUS ipc_trans(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(req, trans);
681 case TRANSACT_DCERPCCMD:
682 status = ipc_dcerpc_cmd(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;
737 /* register ourselves with the NTVFS subsystem. */
738 ret = register_backend("ntvfs", &ops);
740 if (!NT_STATUS_IS_OK(ret)) {
741 DEBUG(0,("Failed to register IPC backend!\n"));