2 Unix SMB/CIFS implementation.
3 default IPC$ NTVFS backend
4 Copyright (C) Andrew Tridgell 2003
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 this implements the IPC$ backend, called by the NTVFS subsystem to
22 handle requests on IPC$ shares
28 /* this is the private structure used to keep the state of an open
29 ipc$ connection. It needs to keep information about all open
36 /* a list of open pipes */
38 struct pipe_state *next, *prev;
40 const char *pipe_name;
42 struct dcesrv_state *pipe_state;
49 find the next fnum available on this connection
51 static uint16 find_next_fnum(struct ipc_private *ipc)
56 if (ipc->num_open == 0xFFFF) {
61 ret = ipc->next_fnum++;
63 for (p=ipc->pipe_list; p; p=p->next) {
74 shutdown a single pipe. Called on a close or disconnect
76 static void pipe_shutdown(struct ipc_private *private, struct pipe_state *p)
78 TALLOC_CTX *mem_ctx = private->pipe_list->mem_ctx;
79 dcesrv_endpoint_disconnect(private->pipe_list->pipe_state);
80 DLIST_REMOVE(private->pipe_list, private->pipe_list);
81 talloc_destroy(mem_ctx);
86 find a open pipe give a file descriptor
88 static struct pipe_state *pipe_state_find(struct ipc_private *private, uint16 fnum)
92 for (p=private->pipe_list; p; p=p->next) {
93 if (p->fnum == fnum) {
103 connect to a share - always works
105 static NTSTATUS ipc_connect(struct request_context *req, const char *sharename)
107 struct tcon_context *conn = req->conn;
108 struct ipc_private *private;
110 conn->fs_type = talloc_strdup(conn->mem_ctx, "IPC");
111 conn->dev_type = talloc_strdup(conn->mem_ctx, "IPC");
113 /* prepare the private state for this connection */
114 private = talloc(conn->mem_ctx, sizeof(struct ipc_private));
116 return NT_STATUS_NO_MEMORY;
118 conn->ntvfs_private = (void *)private;
120 private->pipe_list = NULL;
121 private->next_fnum = 1;
122 private->num_open = 0;
128 disconnect from a share
130 static NTSTATUS ipc_disconnect(struct tcon_context *tcon)
132 struct ipc_private *private = tcon->ntvfs_private;
134 /* close any pipes that are open. Discard any unread data */
135 while (private->pipe_list) {
136 pipe_shutdown(private, private->pipe_list);
145 static NTSTATUS ipc_unlink(struct request_context *req, struct smb_unlink *unl)
147 return NT_STATUS_ACCESS_DENIED;
152 ioctl interface - we don't do any
154 static NTSTATUS ipc_ioctl(struct request_context *req, union smb_ioctl *io)
156 return NT_STATUS_ACCESS_DENIED;
160 check if a directory exists
162 static NTSTATUS ipc_chkpath(struct request_context *req, struct smb_chkpath *cp)
164 return NT_STATUS_ACCESS_DENIED;
168 return info on a pathname
170 static NTSTATUS ipc_qpathinfo(struct request_context *req, union smb_fileinfo *info)
172 return NT_STATUS_ACCESS_DENIED;
176 set info on a pathname
178 static NTSTATUS ipc_setpathinfo(struct request_context *req, union smb_setfileinfo *st)
180 return NT_STATUS_ACCESS_DENIED;
184 open a file - used for MSRPC pipes
186 static NTSTATUS ipc_open(struct request_context *req, union smb_open *oi)
188 struct pipe_state *p;
191 struct dcesrv_endpoint endpoint;
192 struct ipc_private *private = req->conn->ntvfs_private;
194 /* for now only handle NTcreateX style opens */
195 if (oi->generic.level != RAW_OPEN_NTCREATEX) {
196 return NT_STATUS_ACCESS_DENIED;
199 mem_ctx = talloc_init("ipc_open '%s'", oi->ntcreatex.in.fname);
201 return NT_STATUS_NO_MEMORY;
204 p = talloc(mem_ctx, sizeof(struct pipe_state));
206 talloc_destroy(mem_ctx);
207 return NT_STATUS_NO_MEMORY;
209 p->mem_ctx = mem_ctx;
211 p->pipe_name = talloc_strdup(mem_ctx, oi->ntcreatex.in.fname);
213 talloc_destroy(mem_ctx);
214 return NT_STATUS_NO_MEMORY;
217 p->fnum = find_next_fnum(private);
219 talloc_destroy(mem_ctx);
220 return NT_STATUS_TOO_MANY_OPENED_FILES;
223 while (p->pipe_name[0] == '\\') {
228 we're all set, now ask the dcerpc server subsystem to open the
229 endpoint. At this stage the pipe isn't bound, so we don't
230 know what interface the user actually wants, just that they want
231 one of the interfaces attached to this pipe endpoint.
233 TODO: note that we aren't passing any credentials here. We
234 will need to do that once the credentials infrastructure is
238 endpoint.type = ENDPOINT_SMB;
239 endpoint.info.smb_pipe = p->pipe_name;
241 status = dcesrv_endpoint_connect(req->smb, &endpoint, &p->pipe_state);
242 if (!NT_STATUS_IS_OK(status)) {
243 talloc_destroy(mem_ctx);
249 DLIST_ADD(private->pipe_list, p);
251 ZERO_STRUCT(oi->ntcreatex.out);
252 oi->ntcreatex.out.fnum = p->fnum;
260 static NTSTATUS ipc_mkdir(struct request_context *req, union smb_mkdir *md)
262 return NT_STATUS_ACCESS_DENIED;
268 static NTSTATUS ipc_rmdir(struct request_context *req, struct smb_rmdir *rd)
270 return NT_STATUS_ACCESS_DENIED;
274 rename a set of files
276 static NTSTATUS ipc_rename(struct request_context *req, union smb_rename *ren)
278 return NT_STATUS_ACCESS_DENIED;
284 static NTSTATUS ipc_copy(struct request_context *req, struct smb_copy *cp)
286 return NT_STATUS_ACCESS_DENIED;
292 static NTSTATUS ipc_read(struct request_context *req, union smb_read *rd)
294 struct ipc_private *private = req->conn->ntvfs_private;
297 struct pipe_state *p;
300 switch (rd->generic.level) {
302 fnum = rd->read.in.fnum;
303 data.length = rd->read.in.count;
304 data.data = rd->read.out.data;
307 fnum = rd->readx.in.fnum;
308 data.length = rd->readx.in.maxcnt;
309 data.data = rd->readx.out.data;
312 return NT_STATUS_NOT_SUPPORTED;
315 p = pipe_state_find(private, fnum);
317 return NT_STATUS_INVALID_HANDLE;
320 status = dcesrv_output(p->pipe_state, &data);
321 if (!NT_STATUS_IS_OK(status)) {
325 switch (rd->generic.level) {
327 rd->read.out.nread = data.length;
330 rd->readx.out.remaining = 0;
331 rd->readx.out.compaction_mode = 0;
332 rd->readx.out.nread = data.length;
335 return NT_STATUS_NOT_SUPPORTED;
344 static NTSTATUS ipc_write(struct request_context *req, union smb_write *wr)
346 struct ipc_private *private = req->conn->ntvfs_private;
349 struct pipe_state *p;
352 switch (wr->generic.level) {
353 case RAW_WRITE_WRITE:
354 fnum = wr->write.in.fnum;
355 data.data = wr->write.in.data;
356 data.length = wr->write.in.count;
359 case RAW_WRITE_WRITEX:
360 fnum = wr->writex.in.fnum;
361 data.data = wr->writex.in.data;
362 data.length = wr->writex.in.count;
366 return NT_STATUS_NOT_SUPPORTED;
369 p = pipe_state_find(private, fnum);
371 return NT_STATUS_INVALID_HANDLE;
374 status = dcesrv_input(p->pipe_state, &data);
375 if (!NT_STATUS_IS_OK(status)) {
379 switch (wr->generic.level) {
380 case RAW_WRITE_WRITE:
381 wr->write.out.nwritten = data.length;
383 case RAW_WRITE_WRITEX:
384 wr->writex.out.nwritten = data.length;
385 wr->writex.out.remaining = 0;
388 return NT_STATUS_NOT_SUPPORTED;
397 static NTSTATUS ipc_seek(struct request_context *req, struct smb_seek *io)
399 return NT_STATUS_ACCESS_DENIED;
405 static NTSTATUS ipc_flush(struct request_context *req, struct smb_flush *io)
407 return NT_STATUS_ACCESS_DENIED;
413 static NTSTATUS ipc_close(struct request_context *req, union smb_close *io)
415 struct ipc_private *private = req->conn->ntvfs_private;
416 struct pipe_state *p;
418 if (io->generic.level != RAW_CLOSE_CLOSE) {
419 return NT_STATUS_ACCESS_DENIED;
422 p = pipe_state_find(private, io->close.in.fnum);
424 return NT_STATUS_INVALID_HANDLE;
427 pipe_shutdown(private, p);
434 exit - closing files?
436 static NTSTATUS ipc_exit(struct request_context *req)
438 return NT_STATUS_ACCESS_DENIED;
444 static NTSTATUS ipc_lock(struct request_context *req, union smb_lock *lck)
446 return NT_STATUS_ACCESS_DENIED;
450 set info on a open file
452 static NTSTATUS ipc_setfileinfo(struct request_context *req, union smb_setfileinfo *info)
454 return NT_STATUS_ACCESS_DENIED;
458 query info on a open file
460 static NTSTATUS ipc_qfileinfo(struct request_context *req, union smb_fileinfo *info)
462 return NT_STATUS_ACCESS_DENIED;
467 return filesystem info
469 static NTSTATUS ipc_fsinfo(struct request_context *req, union smb_fsinfo *fs)
471 return NT_STATUS_ACCESS_DENIED;
475 return print queue info
477 static NTSTATUS ipc_lpq(struct request_context *req, union smb_lpq *lpq)
479 return NT_STATUS_ACCESS_DENIED;
483 list files in a directory matching a wildcard pattern
485 NTSTATUS ipc_search_first(struct request_context *req, union smb_search_first *io,
486 void *search_private,
487 BOOL (*callback)(void *, union smb_search_data *))
489 return NT_STATUS_ACCESS_DENIED;
493 continue listing files in a directory
495 NTSTATUS ipc_search_next(struct request_context *req, union smb_search_next *io,
496 void *search_private,
497 BOOL (*callback)(void *, union smb_search_data *))
499 return NT_STATUS_ACCESS_DENIED;
503 end listing files in a directory
505 NTSTATUS ipc_search_close(struct request_context *req, union smb_search_close *io)
507 return NT_STATUS_ACCESS_DENIED;
511 /* SMBtrans - used to provide access to SMB pipes */
512 static NTSTATUS ipc_trans(struct request_context *req, struct smb_trans2 *trans)
514 struct pipe_state *p;
515 struct ipc_private *private = req->conn->ntvfs_private;
518 if (trans->in.setup_count != 2 ||
519 trans->in.setup[0] != TRANSACT_DCERPCCMD) {
520 return NT_STATUS_INVALID_PARAMETER;
523 /* the fnum is in setup[1] */
524 p = pipe_state_find(private, trans->in.setup[1]);
526 return NT_STATUS_INVALID_HANDLE;
529 /* pass the data to the dcerpc server. Note that we don't
530 expect this to fail, and things like NDR faults are not
531 reported at this stage. Those sorts of errors happen in the
532 dcesrv_output stage */
533 status = dcesrv_input(p->pipe_state, &trans->in.data);
534 if (!NT_STATUS_IS_OK(status)) {
539 now ask the dcerpc system for some output. This doesn't yet handle
540 async calls. Again, we only expect NT_STATUS_OK. If the call fails then
541 the error is encoded at the dcerpc level
543 status = dcesrv_output(p->pipe_state, &trans->out.data);
544 if (!NT_STATUS_IS_OK(status)) {
548 trans->out.setup_count = 0;
549 trans->out.setup = NULL;
550 trans->out.params = data_blob(NULL, 0);
558 initialialise the IPC backend, registering ourselves with the ntvfs subsystem
560 NTSTATUS ntvfs_ipc_init(void)
563 struct ntvfs_ops ops;
567 /* fill in all the operations */
569 ops.type = NTVFS_IPC;
570 ops.connect = ipc_connect;
571 ops.disconnect = ipc_disconnect;
572 ops.unlink = ipc_unlink;
573 ops.chkpath = ipc_chkpath;
574 ops.qpathinfo = ipc_qpathinfo;
575 ops.setpathinfo = ipc_setpathinfo;
577 ops.mkdir = ipc_mkdir;
578 ops.rmdir = ipc_rmdir;
579 ops.rename = ipc_rename;
581 ops.ioctl = ipc_ioctl;
583 ops.write = ipc_write;
585 ops.flush = ipc_flush;
586 ops.close = ipc_close;
589 ops.setfileinfo = ipc_setfileinfo;
590 ops.qfileinfo = ipc_qfileinfo;
591 ops.fsinfo = ipc_fsinfo;
593 ops.search_first = ipc_search_first;
594 ops.search_next = ipc_search_next;
595 ops.search_close = ipc_search_close;
596 ops.trans = ipc_trans;
598 /* register ourselves with the NTVFS subsystem. */
599 ret = register_backend("ntvfs", &ops);
601 if (!NT_STATUS_IS_OK(ret)) {
602 DEBUG(0,("Failed to register IPC backend!\n"));