2 Unix SMB/CIFS implementation.
3 default IPC$ NTVFS backend
5 Copyright (C) Andrew Tridgell 2003
6 Copyright (C) Stefan (metze) Metzmacher 2004-2005
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 3 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, see <http://www.gnu.org/licenses/>.
22 this implements the IPC$ backend, called by the NTVFS subsystem to
23 handle requests on IPC$ shares
28 #include "../lib/util/dlinklist.h"
29 #include "ntvfs/ntvfs.h"
30 #include "../librpc/gen_ndr/rap.h"
31 #include "ntvfs/ipc/proto.h"
32 #include "../libcli/smb/smb_constants.h"
33 #include "param/param.h"
34 #include "../lib/tsocket/tsocket.h"
35 #include "../libcli/named_pipe_auth/npa_tstream.h"
36 #include "auth/auth.h"
37 #include "auth/auth_sam_reply.h"
38 #include "lib/socket/socket.h"
39 #include "auth/credentials/credentials.h"
40 #include "auth/credentials/credentials_krb5.h"
41 #include "system/kerberos.h"
42 #include "system/gssapi.h"
43 #include "system/locale.h"
44 #include "system/filesys.h"
46 /* this is the private structure used to keep the state of an open
47 ipc$ connection. It needs to keep information about all open
50 struct ntvfs_module_context
*ntvfs
;
52 /* a list of open pipes */
54 struct pipe_state
*next
, *prev
;
55 struct ipc_private
*ipriv
;
56 const char *pipe_name
;
57 struct ntvfs_handle
*handle
;
58 struct tstream_context
*npipe
;
60 uint16_t device_state
;
61 uint64_t allocation_size
;
62 struct tevent_queue
*write_queue
;
63 struct tevent_queue
*read_queue
;
69 find a open pipe give a file handle
71 static struct pipe_state
*pipe_state_find(struct ipc_private
*ipriv
, struct ntvfs_handle
*handle
)
76 p
= ntvfs_handle_get_backend_data(handle
, ipriv
->ntvfs
);
79 s
= talloc_get_type(p
, struct pipe_state
);
86 find a open pipe give a wire fnum
88 static struct pipe_state
*pipe_state_find_key(struct ipc_private
*ipriv
, struct ntvfs_request
*req
, const DATA_BLOB
*key
)
90 struct ntvfs_handle
*h
;
92 h
= ntvfs_handle_search_by_wire_key(ipriv
->ntvfs
, req
, key
);
95 return pipe_state_find(ipriv
, h
);
100 connect to a share - always works
102 static NTSTATUS
ipc_connect(struct ntvfs_module_context
*ntvfs
,
103 struct ntvfs_request
*req
,
104 union smb_tcon
* tcon
)
106 struct ipc_private
*ipriv
;
107 const char *sharename
;
109 switch (tcon
->generic
.level
) {
111 sharename
= tcon
->tcon
.in
.service
;
114 sharename
= tcon
->tconx
.in
.path
;
117 sharename
= tcon
->smb2
.in
.path
;
120 return NT_STATUS_INVALID_LEVEL
;
123 if (strncmp(sharename
, "\\\\", 2) == 0) {
124 char *p
= strchr(sharename
+2, '\\');
130 ntvfs
->ctx
->fs_type
= talloc_strdup(ntvfs
->ctx
, "IPC");
131 NT_STATUS_HAVE_NO_MEMORY(ntvfs
->ctx
->fs_type
);
133 ntvfs
->ctx
->dev_type
= talloc_strdup(ntvfs
->ctx
, "IPC");
134 NT_STATUS_HAVE_NO_MEMORY(ntvfs
->ctx
->dev_type
);
136 if (tcon
->generic
.level
== RAW_TCON_TCONX
) {
137 tcon
->tconx
.out
.fs_type
= ntvfs
->ctx
->fs_type
;
138 tcon
->tconx
.out
.dev_type
= ntvfs
->ctx
->dev_type
;
141 /* prepare the private state for this connection */
142 ipriv
= talloc(ntvfs
, struct ipc_private
);
143 NT_STATUS_HAVE_NO_MEMORY(ipriv
);
145 ntvfs
->private_data
= ipriv
;
147 ipriv
->ntvfs
= ntvfs
;
148 ipriv
->pipe_list
= NULL
;
154 disconnect from a share
156 static NTSTATUS
ipc_disconnect(struct ntvfs_module_context
*ntvfs
)
164 static NTSTATUS
ipc_unlink(struct ntvfs_module_context
*ntvfs
,
165 struct ntvfs_request
*req
,
166 union smb_unlink
*unl
)
168 return NT_STATUS_ACCESS_DENIED
;
172 check if a directory exists
174 static NTSTATUS
ipc_chkpath(struct ntvfs_module_context
*ntvfs
,
175 struct ntvfs_request
*req
,
176 union smb_chkpath
*cp
)
178 return NT_STATUS_ACCESS_DENIED
;
182 return info on a pathname
184 static NTSTATUS
ipc_qpathinfo(struct ntvfs_module_context
*ntvfs
,
185 struct ntvfs_request
*req
, union smb_fileinfo
*info
)
187 switch (info
->generic
.level
) {
188 case RAW_FILEINFO_GENERIC
:
189 return NT_STATUS_INVALID_DEVICE_REQUEST
;
190 case RAW_FILEINFO_GETATTR
:
191 return NT_STATUS_ACCESS_DENIED
;
193 return ntvfs_map_qpathinfo(ntvfs
, req
, info
);
198 set info on a pathname
200 static NTSTATUS
ipc_setpathinfo(struct ntvfs_module_context
*ntvfs
,
201 struct ntvfs_request
*req
, union smb_setfileinfo
*st
)
203 return NT_STATUS_ACCESS_DENIED
;
208 destroy a open pipe structure
210 static int ipc_fd_destructor(struct pipe_state
*p
)
212 DLIST_REMOVE(p
->ipriv
->pipe_list
, p
);
213 ntvfs_handle_remove_backend_data(p
->handle
, p
->ipriv
->ntvfs
);
217 struct ipc_open_state
{
218 struct ipc_private
*ipriv
;
219 struct pipe_state
*p
;
220 struct ntvfs_request
*req
;
222 struct auth_session_info_transport
*session_info_transport
;
225 static void ipc_open_done(struct tevent_req
*subreq
);
228 check the pipename is valid
230 static NTSTATUS
validate_pipename(const char *name
)
233 if (!isalnum(*name
) && *name
!= '_') {
234 return NT_STATUS_INVALID_PARAMETER
;
242 open a file - used for MSRPC pipes
244 static NTSTATUS
ipc_open(struct ntvfs_module_context
*ntvfs
,
245 struct ntvfs_request
*req
, union smb_open
*oi
)
248 struct pipe_state
*p
;
249 struct ipc_private
*ipriv
= talloc_get_type_abort(ntvfs
->private_data
,
251 struct ntvfs_handle
*h
;
252 struct ipc_open_state
*state
;
253 struct tevent_req
*subreq
;
255 const char *directory
;
256 const struct tsocket_address
*client_addr
;
257 const struct tsocket_address
*server_addr
;
259 switch (oi
->generic
.level
) {
260 case RAW_OPEN_NTCREATEX
:
261 case RAW_OPEN_NTTRANS_CREATE
:
262 fname
= oi
->ntcreatex
.in
.fname
;
263 while (fname
[0] == '\\') fname
++;
266 fname
= oi
->openx
.in
.fname
;
267 while (fname
[0] == '\\') fname
++;
268 if (strncasecmp(fname
, "PIPE\\", 5) != 0) {
269 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD
;
271 while (fname
[0] == '\\') fname
++;
274 fname
= oi
->smb2
.in
.fname
;
277 return NT_STATUS_NOT_SUPPORTED
;
280 directory
= talloc_asprintf(req
, "%s/np",
281 lpcfg_ncalrpc_dir(ipriv
->ntvfs
->ctx
->lp_ctx
));
282 NT_STATUS_HAVE_NO_MEMORY(directory
);
284 state
= talloc(req
, struct ipc_open_state
);
285 NT_STATUS_HAVE_NO_MEMORY(state
);
287 status
= ntvfs_handle_new(ntvfs
, req
, &h
);
288 NT_STATUS_NOT_OK_RETURN(status
);
290 p
= talloc(h
, struct pipe_state
);
291 NT_STATUS_HAVE_NO_MEMORY(p
);
293 /* check for valid characters in name */
294 fname
= strlower_talloc(p
, fname
);
296 status
= validate_pipename(fname
);
297 NT_STATUS_NOT_OK_RETURN(status
);
299 p
->pipe_name
= talloc_asprintf(p
, "\\pipe\\%s", fname
);
300 NT_STATUS_HAVE_NO_MEMORY(p
->pipe_name
);
305 p
->write_queue
= tevent_queue_create(p
, "ipc_write_queue");
306 NT_STATUS_HAVE_NO_MEMORY(p
->write_queue
);
308 p
->read_queue
= tevent_queue_create(p
, "ipc_read_queue");
309 NT_STATUS_HAVE_NO_MEMORY(p
->read_queue
);
311 state
->ipriv
= ipriv
;
316 status
= auth_session_info_transport_from_session(state
,
318 ipriv
->ntvfs
->ctx
->event_ctx
,
319 ipriv
->ntvfs
->ctx
->lp_ctx
,
320 &state
->session_info_transport
);
322 NT_STATUS_NOT_OK_RETURN(status
);
324 client_addr
= ntvfs_get_local_address(ipriv
->ntvfs
);
325 server_addr
= ntvfs_get_remote_address(ipriv
->ntvfs
);
327 subreq
= tstream_npa_connect_send(p
,
328 ipriv
->ntvfs
->ctx
->event_ctx
,
335 state
->session_info_transport
);
336 NT_STATUS_HAVE_NO_MEMORY(subreq
);
337 tevent_req_set_callback(subreq
, ipc_open_done
, state
);
339 req
->async_states
->state
|= NTVFS_ASYNC_STATE_ASYNC
;
343 static void ipc_open_done(struct tevent_req
*subreq
)
345 struct ipc_open_state
*state
= tevent_req_callback_data(subreq
,
346 struct ipc_open_state
);
347 struct ipc_private
*ipriv
= state
->ipriv
;
348 struct pipe_state
*p
= state
->p
;
349 struct ntvfs_request
*req
= state
->req
;
350 union smb_open
*oi
= state
->oi
;
355 ret
= tstream_npa_connect_recv(subreq
, &sys_errno
,
359 &p
->allocation_size
);
362 status
= map_nt_error_from_unix_common(sys_errno
);
366 DLIST_ADD(ipriv
->pipe_list
, p
);
367 talloc_set_destructor(p
, ipc_fd_destructor
);
369 status
= ntvfs_handle_set_backend_data(p
->handle
, ipriv
->ntvfs
, p
);
370 if (!NT_STATUS_IS_OK(status
)) {
374 switch (oi
->generic
.level
) {
375 case RAW_OPEN_NTCREATEX
:
376 ZERO_STRUCT(oi
->ntcreatex
.out
);
377 oi
->ntcreatex
.out
.file
.ntvfs
= p
->handle
;
378 oi
->ntcreatex
.out
.oplock_level
= 0;
379 oi
->ntcreatex
.out
.create_action
= NTCREATEX_ACTION_EXISTED
;
380 oi
->ntcreatex
.out
.create_time
= 0;
381 oi
->ntcreatex
.out
.access_time
= 0;
382 oi
->ntcreatex
.out
.write_time
= 0;
383 oi
->ntcreatex
.out
.change_time
= 0;
384 oi
->ntcreatex
.out
.attrib
= FILE_ATTRIBUTE_NORMAL
;
385 oi
->ntcreatex
.out
.alloc_size
= p
->allocation_size
;
386 oi
->ntcreatex
.out
.size
= 0;
387 oi
->ntcreatex
.out
.file_type
= p
->file_type
;
388 oi
->ntcreatex
.out
.ipc_state
= p
->device_state
;
389 oi
->ntcreatex
.out
.is_directory
= 0;
392 ZERO_STRUCT(oi
->openx
.out
);
393 oi
->openx
.out
.file
.ntvfs
= p
->handle
;
394 oi
->openx
.out
.attrib
= FILE_ATTRIBUTE_NORMAL
;
395 oi
->openx
.out
.write_time
= 0;
396 oi
->openx
.out
.size
= 0;
397 oi
->openx
.out
.access
= 0;
398 oi
->openx
.out
.ftype
= p
->file_type
;
399 oi
->openx
.out
.devstate
= p
->device_state
;
400 oi
->openx
.out
.action
= 0;
401 oi
->openx
.out
.unique_fid
= 0;
402 oi
->openx
.out
.access_mask
= 0;
403 oi
->openx
.out
.unknown
= 0;
406 ZERO_STRUCT(oi
->smb2
.out
);
407 oi
->smb2
.out
.file
.ntvfs
= p
->handle
;
408 oi
->smb2
.out
.oplock_level
= oi
->smb2
.in
.oplock_level
;
409 oi
->smb2
.out
.create_action
= NTCREATEX_ACTION_EXISTED
;
410 oi
->smb2
.out
.create_time
= 0;
411 oi
->smb2
.out
.access_time
= 0;
412 oi
->smb2
.out
.write_time
= 0;
413 oi
->smb2
.out
.change_time
= 0;
414 oi
->smb2
.out
.alloc_size
= p
->allocation_size
;
415 oi
->smb2
.out
.size
= 0;
416 oi
->smb2
.out
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
417 oi
->smb2
.out
.reserved2
= 0;
424 req
->async_states
->status
= status
;
425 req
->async_states
->send_fn(req
);
431 static NTSTATUS
ipc_mkdir(struct ntvfs_module_context
*ntvfs
,
432 struct ntvfs_request
*req
, union smb_mkdir
*md
)
434 return NT_STATUS_ACCESS_DENIED
;
440 static NTSTATUS
ipc_rmdir(struct ntvfs_module_context
*ntvfs
,
441 struct ntvfs_request
*req
, struct smb_rmdir
*rd
)
443 return NT_STATUS_ACCESS_DENIED
;
447 rename a set of files
449 static NTSTATUS
ipc_rename(struct ntvfs_module_context
*ntvfs
,
450 struct ntvfs_request
*req
, union smb_rename
*ren
)
452 return NT_STATUS_ACCESS_DENIED
;
458 static NTSTATUS
ipc_copy(struct ntvfs_module_context
*ntvfs
,
459 struct ntvfs_request
*req
, struct smb_copy
*cp
)
461 return NT_STATUS_ACCESS_DENIED
;
464 struct ipc_readv_next_vector_state
{
471 static void ipc_readv_next_vector_init(struct ipc_readv_next_vector_state
*s
,
472 uint8_t *buf
, size_t len
)
477 s
->len
= MIN(len
, UINT16_MAX
);
480 static int ipc_readv_next_vector(struct tstream_context
*stream
,
483 struct iovec
**_vector
,
486 struct ipc_readv_next_vector_state
*state
=
487 (struct ipc_readv_next_vector_state
*)private_data
;
488 struct iovec
*vector
;
492 if (state
->ofs
== state
->len
) {
498 pending
= tstream_pending_bytes(stream
);
503 if (pending
== 0 && state
->ofs
!= 0) {
504 /* return a short read */
511 /* we want at least one byte and recheck again */
514 size_t missing
= state
->len
- state
->ofs
;
515 if (pending
> missing
) {
516 /* there's more available */
517 state
->remaining
= pending
- missing
;
520 /* read what we can get and recheck in the next cycle */
525 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
530 vector
[0].iov_base
= (char *) (state
->buf
+ state
->ofs
);
531 vector
[0].iov_len
= wanted
;
533 state
->ofs
+= wanted
;
540 struct ipc_read_state
{
541 struct ipc_private
*ipriv
;
542 struct pipe_state
*p
;
543 struct ntvfs_request
*req
;
545 struct ipc_readv_next_vector_state next_vector
;
548 static void ipc_read_done(struct tevent_req
*subreq
);
553 static NTSTATUS
ipc_read(struct ntvfs_module_context
*ntvfs
,
554 struct ntvfs_request
*req
, union smb_read
*rd
)
556 struct ipc_private
*ipriv
= talloc_get_type_abort(ntvfs
->private_data
,
558 struct pipe_state
*p
;
559 struct ipc_read_state
*state
;
560 struct tevent_req
*subreq
;
562 if (rd
->generic
.level
!= RAW_READ_GENERIC
) {
563 return ntvfs_map_read(ntvfs
, req
, rd
);
566 p
= pipe_state_find(ipriv
, rd
->readx
.in
.file
.ntvfs
);
568 return NT_STATUS_INVALID_HANDLE
;
571 state
= talloc(req
, struct ipc_read_state
);
572 NT_STATUS_HAVE_NO_MEMORY(state
);
574 state
->ipriv
= ipriv
;
579 /* rd->readx.out.data is already allocated */
580 ipc_readv_next_vector_init(&state
->next_vector
,
582 rd
->readx
.in
.maxcnt
);
584 subreq
= tstream_readv_pdu_queue_send(req
,
585 ipriv
->ntvfs
->ctx
->event_ctx
,
588 ipc_readv_next_vector
,
589 &state
->next_vector
);
590 NT_STATUS_HAVE_NO_MEMORY(subreq
);
591 tevent_req_set_callback(subreq
, ipc_read_done
, state
);
593 req
->async_states
->state
|= NTVFS_ASYNC_STATE_ASYNC
;
597 static void ipc_read_done(struct tevent_req
*subreq
)
599 struct ipc_read_state
*state
=
600 tevent_req_callback_data(subreq
,
601 struct ipc_read_state
);
602 struct ntvfs_request
*req
= state
->req
;
603 union smb_read
*rd
= state
->rd
;
608 ret
= tstream_readv_pdu_queue_recv(subreq
, &sys_errno
);
611 status
= map_nt_error_from_unix_common(sys_errno
);
615 status
= NT_STATUS_OK
;
616 if (state
->next_vector
.remaining
> 0) {
617 status
= STATUS_BUFFER_OVERFLOW
;
620 rd
->readx
.out
.remaining
= state
->next_vector
.remaining
;
621 rd
->readx
.out
.compaction_mode
= 0;
622 rd
->readx
.out
.nread
= ret
;
625 req
->async_states
->status
= status
;
626 req
->async_states
->send_fn(req
);
629 struct ipc_write_state
{
630 struct ipc_private
*ipriv
;
631 struct pipe_state
*p
;
632 struct ntvfs_request
*req
;
637 static void ipc_write_done(struct tevent_req
*subreq
);
642 static NTSTATUS
ipc_write(struct ntvfs_module_context
*ntvfs
,
643 struct ntvfs_request
*req
, union smb_write
*wr
)
645 struct ipc_private
*ipriv
= talloc_get_type_abort(ntvfs
->private_data
,
647 struct pipe_state
*p
;
648 struct tevent_req
*subreq
;
649 struct ipc_write_state
*state
;
651 if (wr
->generic
.level
!= RAW_WRITE_GENERIC
) {
652 return ntvfs_map_write(ntvfs
, req
, wr
);
655 p
= pipe_state_find(ipriv
, wr
->writex
.in
.file
.ntvfs
);
657 return NT_STATUS_INVALID_HANDLE
;
660 state
= talloc(req
, struct ipc_write_state
);
661 NT_STATUS_HAVE_NO_MEMORY(state
);
663 state
->ipriv
= ipriv
;
667 state
->iov
.iov_base
= discard_const_p(void, wr
->writex
.in
.data
);
668 state
->iov
.iov_len
= wr
->writex
.in
.count
;
670 subreq
= tstream_writev_queue_send(state
,
671 ipriv
->ntvfs
->ctx
->event_ctx
,
675 NT_STATUS_HAVE_NO_MEMORY(subreq
);
676 tevent_req_set_callback(subreq
, ipc_write_done
, state
);
678 req
->async_states
->state
|= NTVFS_ASYNC_STATE_ASYNC
;
682 static void ipc_write_done(struct tevent_req
*subreq
)
684 struct ipc_write_state
*state
=
685 tevent_req_callback_data(subreq
,
686 struct ipc_write_state
);
687 struct ntvfs_request
*req
= state
->req
;
688 union smb_write
*wr
= state
->wr
;
693 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
696 status
= map_nt_error_from_unix_common(sys_errno
);
700 status
= NT_STATUS_OK
;
702 wr
->writex
.out
.nwritten
= ret
;
703 wr
->writex
.out
.remaining
= 0;
706 req
->async_states
->status
= status
;
707 req
->async_states
->send_fn(req
);
713 static NTSTATUS
ipc_seek(struct ntvfs_module_context
*ntvfs
,
714 struct ntvfs_request
*req
,
717 return NT_STATUS_ACCESS_DENIED
;
723 static NTSTATUS
ipc_flush(struct ntvfs_module_context
*ntvfs
,
724 struct ntvfs_request
*req
,
727 return NT_STATUS_ACCESS_DENIED
;
733 static NTSTATUS
ipc_close(struct ntvfs_module_context
*ntvfs
,
734 struct ntvfs_request
*req
, union smb_close
*io
)
736 struct ipc_private
*ipriv
= talloc_get_type_abort(ntvfs
->private_data
,
738 struct pipe_state
*p
;
740 if (io
->generic
.level
!= RAW_CLOSE_CLOSE
) {
741 return ntvfs_map_close(ntvfs
, req
, io
);
744 p
= pipe_state_find(ipriv
, io
->close
.in
.file
.ntvfs
);
746 return NT_STATUS_INVALID_HANDLE
;
757 static NTSTATUS
ipc_exit(struct ntvfs_module_context
*ntvfs
,
758 struct ntvfs_request
*req
)
760 struct ipc_private
*ipriv
= talloc_get_type_abort(ntvfs
->private_data
,
762 struct pipe_state
*p
, *next
;
764 for (p
=ipriv
->pipe_list
; p
; p
=next
) {
766 if (p
->handle
->session_info
== req
->session_info
&&
767 p
->handle
->smbpid
== req
->smbpid
) {
776 logoff - closing files open by the user
778 static NTSTATUS
ipc_logoff(struct ntvfs_module_context
*ntvfs
,
779 struct ntvfs_request
*req
)
781 struct ipc_private
*ipriv
= talloc_get_type_abort(ntvfs
->private_data
,
783 struct pipe_state
*p
, *next
;
785 for (p
=ipriv
->pipe_list
; p
; p
=next
) {
787 if (p
->handle
->session_info
== req
->session_info
) {
796 setup for an async call
798 static NTSTATUS
ipc_async_setup(struct ntvfs_module_context
*ntvfs
,
799 struct ntvfs_request
*req
,
808 static NTSTATUS
ipc_cancel(struct ntvfs_module_context
*ntvfs
,
809 struct ntvfs_request
*req
)
811 return NT_STATUS_UNSUCCESSFUL
;
817 static NTSTATUS
ipc_lock(struct ntvfs_module_context
*ntvfs
,
818 struct ntvfs_request
*req
, union smb_lock
*lck
)
820 return NT_STATUS_ACCESS_DENIED
;
824 set info on a open file
826 static NTSTATUS
ipc_setfileinfo(struct ntvfs_module_context
*ntvfs
,
827 struct ntvfs_request
*req
, union smb_setfileinfo
*info
)
829 return NT_STATUS_ACCESS_DENIED
;
833 query info on a open file
835 static NTSTATUS
ipc_qfileinfo(struct ntvfs_module_context
*ntvfs
,
836 struct ntvfs_request
*req
, union smb_fileinfo
*info
)
838 struct ipc_private
*ipriv
= talloc_get_type_abort(ntvfs
->private_data
,
840 struct pipe_state
*p
= pipe_state_find(ipriv
, info
->generic
.in
.file
.ntvfs
);
842 return NT_STATUS_INVALID_HANDLE
;
844 switch (info
->generic
.level
) {
845 case RAW_FILEINFO_GENERIC
:
847 ZERO_STRUCT(info
->generic
.out
);
848 info
->generic
.out
.attrib
= FILE_ATTRIBUTE_NORMAL
;
849 info
->generic
.out
.fname
.s
= strrchr(p
->pipe_name
, '\\');
850 info
->generic
.out
.alloc_size
= 4096;
851 info
->generic
.out
.nlink
= 1;
852 /* What the heck? Match Win2k3: IPC$ pipes are delete pending */
853 info
->generic
.out
.delete_pending
= 1;
856 case RAW_FILEINFO_ALT_NAME_INFO
:
857 case RAW_FILEINFO_ALT_NAME_INFORMATION
:
858 case RAW_FILEINFO_STREAM_INFO
:
859 case RAW_FILEINFO_STREAM_INFORMATION
:
860 case RAW_FILEINFO_COMPRESSION_INFO
:
861 case RAW_FILEINFO_COMPRESSION_INFORMATION
:
862 case RAW_FILEINFO_NETWORK_OPEN_INFORMATION
:
863 case RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION
:
864 return NT_STATUS_INVALID_PARAMETER
;
865 case RAW_FILEINFO_ALL_EAS
:
866 return NT_STATUS_ACCESS_DENIED
;
868 return ntvfs_map_qfileinfo(ntvfs
, req
, info
);
874 return filesystem info
876 static NTSTATUS
ipc_fsinfo(struct ntvfs_module_context
*ntvfs
,
877 struct ntvfs_request
*req
, union smb_fsinfo
*fs
)
879 return NT_STATUS_ACCESS_DENIED
;
883 return print queue info
885 static NTSTATUS
ipc_lpq(struct ntvfs_module_context
*ntvfs
,
886 struct ntvfs_request
*req
, union smb_lpq
*lpq
)
888 return NT_STATUS_ACCESS_DENIED
;
892 list files in a directory matching a wildcard pattern
894 static NTSTATUS
ipc_search_first(struct ntvfs_module_context
*ntvfs
,
895 struct ntvfs_request
*req
, union smb_search_first
*io
,
896 void *search_private
,
897 bool (*callback
)(void *, const union smb_search_data
*))
899 return NT_STATUS_ACCESS_DENIED
;
903 continue listing files in a directory
905 static NTSTATUS
ipc_search_next(struct ntvfs_module_context
*ntvfs
,
906 struct ntvfs_request
*req
, union smb_search_next
*io
,
907 void *search_private
,
908 bool (*callback
)(void *, const union smb_search_data
*))
910 return NT_STATUS_ACCESS_DENIED
;
914 end listing files in a directory
916 static NTSTATUS
ipc_search_close(struct ntvfs_module_context
*ntvfs
,
917 struct ntvfs_request
*req
, union smb_search_close
*io
)
919 return NT_STATUS_ACCESS_DENIED
;
922 struct ipc_trans_state
{
923 struct ipc_private
*ipriv
;
924 struct pipe_state
*p
;
925 struct ntvfs_request
*req
;
926 struct smb_trans2
*trans
;
927 struct iovec writev_iov
;
928 struct ipc_readv_next_vector_state next_vector
;
931 static void ipc_trans_writev_done(struct tevent_req
*subreq
);
932 static void ipc_trans_readv_done(struct tevent_req
*subreq
);
934 /* SMBtrans - handle a DCERPC command */
935 static NTSTATUS
ipc_dcerpc_cmd(struct ntvfs_module_context
*ntvfs
,
936 struct ntvfs_request
*req
, struct smb_trans2
*trans
)
938 struct ipc_private
*ipriv
= talloc_get_type_abort(ntvfs
->private_data
,
940 struct pipe_state
*p
;
943 struct ipc_trans_state
*state
;
944 struct tevent_req
*subreq
;
947 * the fnum is in setup[1], a 16 bit value
948 * the setup[*] values are already in host byteorder
949 * but ntvfs_handle_search_by_wire_key() expects
952 SSVAL(&fnum
, 0, trans
->in
.setup
[1]);
953 fnum_key
= data_blob_const(&fnum
, 2);
955 p
= pipe_state_find_key(ipriv
, req
, &fnum_key
);
957 return NT_STATUS_INVALID_HANDLE
;
961 * Trans requests are only allowed
962 * if no other Trans or Read is active
964 if (tevent_queue_length(p
->read_queue
) > 0) {
965 return NT_STATUS_PIPE_BUSY
;
968 state
= talloc(req
, struct ipc_trans_state
);
969 NT_STATUS_HAVE_NO_MEMORY(state
);
971 trans
->out
.setup_count
= 0;
972 trans
->out
.setup
= NULL
;
973 trans
->out
.params
= data_blob(NULL
, 0);
974 trans
->out
.data
= data_blob_talloc(req
, NULL
, trans
->in
.max_data
);
975 NT_STATUS_HAVE_NO_MEMORY(trans
->out
.data
.data
);
977 state
->ipriv
= ipriv
;
980 state
->trans
= trans
;
981 state
->writev_iov
.iov_base
= (char *) trans
->in
.data
.data
;
982 state
->writev_iov
.iov_len
= trans
->in
.data
.length
;
984 ipc_readv_next_vector_init(&state
->next_vector
,
985 trans
->out
.data
.data
,
986 trans
->out
.data
.length
);
988 subreq
= tstream_writev_queue_send(state
,
989 ipriv
->ntvfs
->ctx
->event_ctx
,
992 &state
->writev_iov
, 1);
993 NT_STATUS_HAVE_NO_MEMORY(subreq
);
994 tevent_req_set_callback(subreq
, ipc_trans_writev_done
, state
);
996 req
->async_states
->state
|= NTVFS_ASYNC_STATE_ASYNC
;
1000 static void ipc_trans_writev_done(struct tevent_req
*subreq
)
1002 struct ipc_trans_state
*state
=
1003 tevent_req_callback_data(subreq
,
1004 struct ipc_trans_state
);
1005 struct ipc_private
*ipriv
= state
->ipriv
;
1006 struct pipe_state
*p
= state
->p
;
1007 struct ntvfs_request
*req
= state
->req
;
1012 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
1013 TALLOC_FREE(subreq
);
1015 status
= NT_STATUS_PIPE_DISCONNECTED
;
1017 } else if (ret
== -1) {
1018 status
= map_nt_error_from_unix_common(sys_errno
);
1022 subreq
= tstream_readv_pdu_queue_send(state
,
1023 ipriv
->ntvfs
->ctx
->event_ctx
,
1026 ipc_readv_next_vector
,
1027 &state
->next_vector
);
1029 status
= NT_STATUS_NO_MEMORY
;
1032 tevent_req_set_callback(subreq
, ipc_trans_readv_done
, state
);
1036 req
->async_states
->status
= status
;
1037 req
->async_states
->send_fn(req
);
1040 static void ipc_trans_readv_done(struct tevent_req
*subreq
)
1042 struct ipc_trans_state
*state
=
1043 tevent_req_callback_data(subreq
,
1044 struct ipc_trans_state
);
1045 struct ntvfs_request
*req
= state
->req
;
1046 struct smb_trans2
*trans
= state
->trans
;
1051 ret
= tstream_readv_pdu_queue_recv(subreq
, &sys_errno
);
1052 TALLOC_FREE(subreq
);
1054 status
= map_nt_error_from_unix_common(sys_errno
);
1058 status
= NT_STATUS_OK
;
1059 if (state
->next_vector
.remaining
> 0) {
1060 status
= STATUS_BUFFER_OVERFLOW
;
1063 trans
->out
.data
.length
= ret
;
1066 req
->async_states
->status
= status
;
1067 req
->async_states
->send_fn(req
);
1070 /* SMBtrans - set named pipe state */
1071 static NTSTATUS
ipc_set_nm_pipe_state(struct ntvfs_module_context
*ntvfs
,
1072 struct ntvfs_request
*req
, struct smb_trans2
*trans
)
1074 struct ipc_private
*ipriv
= talloc_get_type_abort(ntvfs
->private_data
,
1075 struct ipc_private
);
1076 struct pipe_state
*p
;
1079 /* the fnum is in setup[1] */
1080 fnum_key
= data_blob_const(&trans
->in
.setup
[1], sizeof(trans
->in
.setup
[1]));
1082 p
= pipe_state_find_key(ipriv
, req
, &fnum_key
);
1084 return NT_STATUS_INVALID_HANDLE
;
1087 if (trans
->in
.params
.length
!= 2) {
1088 return NT_STATUS_INVALID_PARAMETER
;
1092 * TODO: pass this to the tstream_npa logic
1094 p
->device_state
= SVAL(trans
->in
.params
.data
, 0);
1096 trans
->out
.setup_count
= 0;
1097 trans
->out
.setup
= NULL
;
1098 trans
->out
.params
= data_blob(NULL
, 0);
1099 trans
->out
.data
= data_blob(NULL
, 0);
1101 return NT_STATUS_OK
;
1105 /* SMBtrans - used to provide access to SMB pipes */
1106 static NTSTATUS
ipc_trans(struct ntvfs_module_context
*ntvfs
,
1107 struct ntvfs_request
*req
, struct smb_trans2
*trans
)
1111 if (strequal(trans
->in
.trans_name
, "\\PIPE\\LANMAN"))
1112 return ipc_rap_call(req
, ntvfs
->ctx
->event_ctx
, ntvfs
->ctx
->lp_ctx
, trans
);
1114 if (trans
->in
.setup_count
!= 2) {
1115 return NT_STATUS_INVALID_PARAMETER
;
1118 switch (trans
->in
.setup
[0]) {
1119 case TRANSACT_SETNAMEDPIPEHANDLESTATE
:
1120 status
= ipc_set_nm_pipe_state(ntvfs
, req
, trans
);
1122 case TRANSACT_DCERPCCMD
:
1123 status
= ipc_dcerpc_cmd(ntvfs
, req
, trans
);
1126 status
= NT_STATUS_INVALID_PARAMETER
;
1133 struct ipc_ioctl_state
{
1134 struct ipc_private
*ipriv
;
1135 struct pipe_state
*p
;
1136 struct ntvfs_request
*req
;
1137 union smb_ioctl
*io
;
1138 struct iovec writev_iov
;
1139 struct ipc_readv_next_vector_state next_vector
;
1142 static void ipc_ioctl_writev_done(struct tevent_req
*subreq
);
1143 static void ipc_ioctl_readv_done(struct tevent_req
*subreq
);
1145 static NTSTATUS
ipc_ioctl_smb2(struct ntvfs_module_context
*ntvfs
,
1146 struct ntvfs_request
*req
, union smb_ioctl
*io
)
1148 struct ipc_private
*ipriv
= talloc_get_type_abort(ntvfs
->private_data
,
1149 struct ipc_private
);
1150 struct pipe_state
*p
;
1151 struct ipc_ioctl_state
*state
;
1152 struct tevent_req
*subreq
;
1154 switch (io
->smb2
.in
.function
) {
1155 case FSCTL_NAMED_PIPE_READ_WRITE
:
1159 return NT_STATUS_FS_DRIVER_REQUIRED
;
1162 p
= pipe_state_find(ipriv
, io
->smb2
.in
.file
.ntvfs
);
1164 return NT_STATUS_INVALID_HANDLE
;
1168 * Trans requests are only allowed
1169 * if no other Trans or Read is active
1171 if (tevent_queue_length(p
->read_queue
) > 0) {
1172 return NT_STATUS_PIPE_BUSY
;
1175 state
= talloc(req
, struct ipc_ioctl_state
);
1176 NT_STATUS_HAVE_NO_MEMORY(state
);
1178 io
->smb2
.out
._pad
= 0;
1179 io
->smb2
.out
.function
= io
->smb2
.in
.function
;
1180 io
->smb2
.out
.unknown2
= 0;
1181 io
->smb2
.out
.unknown3
= 0;
1182 io
->smb2
.out
.in
= data_blob_null
;
1183 io
->smb2
.out
.out
= data_blob_talloc(req
, NULL
, io
->smb2
.in
.max_response_size
);
1184 NT_STATUS_HAVE_NO_MEMORY(io
->smb2
.out
.out
.data
);
1186 state
->ipriv
= ipriv
;
1190 state
->writev_iov
.iov_base
= (char *) io
->smb2
.in
.out
.data
;
1191 state
->writev_iov
.iov_len
= io
->smb2
.in
.out
.length
;
1193 ipc_readv_next_vector_init(&state
->next_vector
,
1194 io
->smb2
.out
.out
.data
,
1195 io
->smb2
.out
.out
.length
);
1197 subreq
= tstream_writev_queue_send(state
,
1198 ipriv
->ntvfs
->ctx
->event_ctx
,
1201 &state
->writev_iov
, 1);
1202 NT_STATUS_HAVE_NO_MEMORY(subreq
);
1203 tevent_req_set_callback(subreq
, ipc_ioctl_writev_done
, state
);
1205 req
->async_states
->state
|= NTVFS_ASYNC_STATE_ASYNC
;
1206 return NT_STATUS_OK
;
1209 static void ipc_ioctl_writev_done(struct tevent_req
*subreq
)
1211 struct ipc_ioctl_state
*state
=
1212 tevent_req_callback_data(subreq
,
1213 struct ipc_ioctl_state
);
1214 struct ipc_private
*ipriv
= state
->ipriv
;
1215 struct pipe_state
*p
= state
->p
;
1216 struct ntvfs_request
*req
= state
->req
;
1221 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
1222 TALLOC_FREE(subreq
);
1224 status
= map_nt_error_from_unix_common(sys_errno
);
1228 subreq
= tstream_readv_pdu_queue_send(state
,
1229 ipriv
->ntvfs
->ctx
->event_ctx
,
1232 ipc_readv_next_vector
,
1233 &state
->next_vector
);
1235 status
= NT_STATUS_NO_MEMORY
;
1238 tevent_req_set_callback(subreq
, ipc_ioctl_readv_done
, state
);
1242 req
->async_states
->status
= status
;
1243 req
->async_states
->send_fn(req
);
1246 static void ipc_ioctl_readv_done(struct tevent_req
*subreq
)
1248 struct ipc_ioctl_state
*state
=
1249 tevent_req_callback_data(subreq
,
1250 struct ipc_ioctl_state
);
1251 struct ntvfs_request
*req
= state
->req
;
1252 union smb_ioctl
*io
= state
->io
;
1257 ret
= tstream_readv_pdu_queue_recv(subreq
, &sys_errno
);
1258 TALLOC_FREE(subreq
);
1260 status
= map_nt_error_from_unix_common(sys_errno
);
1264 status
= NT_STATUS_OK
;
1265 if (state
->next_vector
.remaining
> 0) {
1266 status
= STATUS_BUFFER_OVERFLOW
;
1269 io
->smb2
.out
.out
.length
= ret
;
1272 req
->async_states
->status
= status
;
1273 req
->async_states
->send_fn(req
);
1279 static NTSTATUS
ipc_ioctl(struct ntvfs_module_context
*ntvfs
,
1280 struct ntvfs_request
*req
, union smb_ioctl
*io
)
1282 switch (io
->generic
.level
) {
1283 case RAW_IOCTL_SMB2
:
1284 return ipc_ioctl_smb2(ntvfs
, req
, io
);
1286 case RAW_IOCTL_SMB2_NO_HANDLE
:
1287 return NT_STATUS_FS_DRIVER_REQUIRED
;
1290 return NT_STATUS_ACCESS_DENIED
;
1296 initialialise the IPC backend, registering ourselves with the ntvfs subsystem
1298 NTSTATUS
ntvfs_ipc_init(void)
1301 struct ntvfs_ops ops
;
1302 NTVFS_CURRENT_CRITICAL_SIZES(vers
);
1306 /* fill in the name and type */
1307 ops
.name
= "default";
1308 ops
.type
= NTVFS_IPC
;
1310 /* fill in all the operations */
1311 ops
.connect_fn
= ipc_connect
;
1312 ops
.disconnect_fn
= ipc_disconnect
;
1313 ops
.unlink_fn
= ipc_unlink
;
1314 ops
.chkpath_fn
= ipc_chkpath
;
1315 ops
.qpathinfo_fn
= ipc_qpathinfo
;
1316 ops
.setpathinfo_fn
= ipc_setpathinfo
;
1317 ops
.open_fn
= ipc_open
;
1318 ops
.mkdir_fn
= ipc_mkdir
;
1319 ops
.rmdir_fn
= ipc_rmdir
;
1320 ops
.rename_fn
= ipc_rename
;
1321 ops
.copy_fn
= ipc_copy
;
1322 ops
.ioctl_fn
= ipc_ioctl
;
1323 ops
.read_fn
= ipc_read
;
1324 ops
.write_fn
= ipc_write
;
1325 ops
.seek_fn
= ipc_seek
;
1326 ops
.flush_fn
= ipc_flush
;
1327 ops
.close_fn
= ipc_close
;
1328 ops
.exit_fn
= ipc_exit
;
1329 ops
.lock_fn
= ipc_lock
;
1330 ops
.setfileinfo_fn
= ipc_setfileinfo
;
1331 ops
.qfileinfo_fn
= ipc_qfileinfo
;
1332 ops
.fsinfo_fn
= ipc_fsinfo
;
1333 ops
.lpq_fn
= ipc_lpq
;
1334 ops
.search_first_fn
= ipc_search_first
;
1335 ops
.search_next_fn
= ipc_search_next
;
1336 ops
.search_close_fn
= ipc_search_close
;
1337 ops
.trans_fn
= ipc_trans
;
1338 ops
.logoff_fn
= ipc_logoff
;
1339 ops
.async_setup_fn
= ipc_async_setup
;
1340 ops
.cancel_fn
= ipc_cancel
;
1342 /* register ourselves with the NTVFS subsystem. */
1343 ret
= ntvfs_register(&ops
, &vers
);
1345 if (!NT_STATUS_IS_OK(ret
)) {
1346 DEBUG(0,("Failed to register IPC backend!\n"));