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/raw/ioctl.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 <gssapi/gssapi.h>
42 #include "system/locale.h"
44 /* this is the private structure used to keep the state of an open
45 ipc$ connection. It needs to keep information about all open
48 struct ntvfs_module_context
*ntvfs
;
50 /* a list of open pipes */
52 struct pipe_state
*next
, *prev
;
53 struct ipc_private
*ipriv
;
54 const char *pipe_name
;
55 struct ntvfs_handle
*handle
;
56 struct tstream_context
*npipe
;
58 uint16_t device_state
;
59 uint64_t allocation_size
;
60 struct tevent_queue
*write_queue
;
61 struct tevent_queue
*read_queue
;
67 find a open pipe give a file handle
69 static struct pipe_state
*pipe_state_find(struct ipc_private
*ipriv
, struct ntvfs_handle
*handle
)
74 p
= ntvfs_handle_get_backend_data(handle
, ipriv
->ntvfs
);
77 s
= talloc_get_type(p
, struct pipe_state
);
84 find a open pipe give a wire fnum
86 static struct pipe_state
*pipe_state_find_key(struct ipc_private
*ipriv
, struct ntvfs_request
*req
, const DATA_BLOB
*key
)
88 struct ntvfs_handle
*h
;
90 h
= ntvfs_handle_search_by_wire_key(ipriv
->ntvfs
, req
, key
);
93 return pipe_state_find(ipriv
, h
);
98 connect to a share - always works
100 static NTSTATUS
ipc_connect(struct ntvfs_module_context
*ntvfs
,
101 struct ntvfs_request
*req
,
102 union smb_tcon
* tcon
)
104 struct ipc_private
*ipriv
;
105 const char *sharename
;
107 switch (tcon
->generic
.level
) {
109 sharename
= tcon
->tcon
.in
.service
;
112 sharename
= tcon
->tconx
.in
.path
;
115 sharename
= tcon
->smb2
.in
.path
;
118 return NT_STATUS_INVALID_LEVEL
;
121 if (strncmp(sharename
, "\\\\", 2) == 0) {
122 char *p
= strchr(sharename
+2, '\\');
128 ntvfs
->ctx
->fs_type
= talloc_strdup(ntvfs
->ctx
, "IPC");
129 NT_STATUS_HAVE_NO_MEMORY(ntvfs
->ctx
->fs_type
);
131 ntvfs
->ctx
->dev_type
= talloc_strdup(ntvfs
->ctx
, "IPC");
132 NT_STATUS_HAVE_NO_MEMORY(ntvfs
->ctx
->dev_type
);
134 if (tcon
->generic
.level
== RAW_TCON_TCONX
) {
135 tcon
->tconx
.out
.fs_type
= ntvfs
->ctx
->fs_type
;
136 tcon
->tconx
.out
.dev_type
= ntvfs
->ctx
->dev_type
;
139 /* prepare the private state for this connection */
140 ipriv
= talloc(ntvfs
, struct ipc_private
);
141 NT_STATUS_HAVE_NO_MEMORY(ipriv
);
143 ntvfs
->private_data
= ipriv
;
145 ipriv
->ntvfs
= ntvfs
;
146 ipriv
->pipe_list
= NULL
;
152 disconnect from a share
154 static NTSTATUS
ipc_disconnect(struct ntvfs_module_context
*ntvfs
)
162 static NTSTATUS
ipc_unlink(struct ntvfs_module_context
*ntvfs
,
163 struct ntvfs_request
*req
,
164 union smb_unlink
*unl
)
166 return NT_STATUS_ACCESS_DENIED
;
170 check if a directory exists
172 static NTSTATUS
ipc_chkpath(struct ntvfs_module_context
*ntvfs
,
173 struct ntvfs_request
*req
,
174 union smb_chkpath
*cp
)
176 return NT_STATUS_ACCESS_DENIED
;
180 return info on a pathname
182 static NTSTATUS
ipc_qpathinfo(struct ntvfs_module_context
*ntvfs
,
183 struct ntvfs_request
*req
, union smb_fileinfo
*info
)
185 switch (info
->generic
.level
) {
186 case RAW_FILEINFO_GENERIC
:
187 return NT_STATUS_INVALID_DEVICE_REQUEST
;
188 case RAW_FILEINFO_GETATTR
:
189 return NT_STATUS_ACCESS_DENIED
;
191 return ntvfs_map_qpathinfo(ntvfs
, req
, info
);
196 set info on a pathname
198 static NTSTATUS
ipc_setpathinfo(struct ntvfs_module_context
*ntvfs
,
199 struct ntvfs_request
*req
, union smb_setfileinfo
*st
)
201 return NT_STATUS_ACCESS_DENIED
;
206 destroy a open pipe structure
208 static int ipc_fd_destructor(struct pipe_state
*p
)
210 DLIST_REMOVE(p
->ipriv
->pipe_list
, p
);
211 ntvfs_handle_remove_backend_data(p
->handle
, p
->ipriv
->ntvfs
);
215 struct ipc_open_state
{
216 struct ipc_private
*ipriv
;
217 struct pipe_state
*p
;
218 struct ntvfs_request
*req
;
220 struct netr_SamInfo3
*info3
;
223 static void ipc_open_done(struct tevent_req
*subreq
);
226 check the pipename is valid
228 static NTSTATUS
validate_pipename(const char *name
)
231 if (!isalnum(*name
)) return NT_STATUS_INVALID_PARAMETER
;
238 open a file - used for MSRPC pipes
240 static NTSTATUS
ipc_open(struct ntvfs_module_context
*ntvfs
,
241 struct ntvfs_request
*req
, union smb_open
*oi
)
244 struct pipe_state
*p
;
245 struct ipc_private
*ipriv
= talloc_get_type_abort(ntvfs
->private_data
,
247 struct ntvfs_handle
*h
;
248 struct ipc_open_state
*state
;
249 struct tevent_req
*subreq
;
251 const char *directory
;
252 const struct tsocket_address
*client_addr
;
253 const struct tsocket_address
*server_addr
;
255 DATA_BLOB delegated_creds
= data_blob_null
;
257 switch (oi
->generic
.level
) {
258 case RAW_OPEN_NTCREATEX
:
259 case RAW_OPEN_NTTRANS_CREATE
:
260 fname
= oi
->ntcreatex
.in
.fname
;
263 fname
= oi
->openx
.in
.fname
;
266 fname
= oi
->smb2
.in
.fname
;
269 return NT_STATUS_NOT_SUPPORTED
;
272 directory
= talloc_asprintf(req
, "%s/np",
273 lpcfg_ncalrpc_dir(ipriv
->ntvfs
->ctx
->lp_ctx
));
274 NT_STATUS_HAVE_NO_MEMORY(directory
);
276 state
= talloc(req
, struct ipc_open_state
);
277 NT_STATUS_HAVE_NO_MEMORY(state
);
279 status
= ntvfs_handle_new(ntvfs
, req
, &h
);
280 NT_STATUS_NOT_OK_RETURN(status
);
282 p
= talloc(h
, struct pipe_state
);
283 NT_STATUS_HAVE_NO_MEMORY(p
);
285 while (fname
[0] == '\\') fname
++;
287 /* check for valid characters in name */
288 fname
= strlower_talloc(p
, fname
);
290 status
= validate_pipename(fname
);
291 NT_STATUS_NOT_OK_RETURN(status
);
293 p
->pipe_name
= talloc_asprintf(p
, "\\pipe\\%s", fname
);
294 NT_STATUS_HAVE_NO_MEMORY(p
->pipe_name
);
299 p
->write_queue
= tevent_queue_create(p
, "ipc_write_queue");
300 NT_STATUS_HAVE_NO_MEMORY(p
->write_queue
);
302 p
->read_queue
= tevent_queue_create(p
, "ipc_read_queue");
303 NT_STATUS_HAVE_NO_MEMORY(p
->read_queue
);
305 state
->ipriv
= ipriv
;
310 status
= auth_convert_server_info_saminfo3(state
,
311 req
->session_info
->server_info
,
313 NT_STATUS_NOT_OK_RETURN(status
);
315 client_addr
= ntvfs_get_local_address(ipriv
->ntvfs
);
316 server_addr
= ntvfs_get_remote_address(ipriv
->ntvfs
);
318 if (req
->session_info
->credentials
) {
319 struct gssapi_creds_container
*gcc
;
321 OM_uint32 minor_status
;
322 gss_buffer_desc cred_token
;
323 const char *error_string
;
325 ret
= cli_credentials_get_client_gss_creds(req
->session_info
->credentials
,
326 ipriv
->ntvfs
->ctx
->event_ctx
,
327 ipriv
->ntvfs
->ctx
->lp_ctx
,
328 &gcc
, &error_string
);
333 gret
= gss_export_cred(&minor_status
,
336 if (gret
!= GSS_S_COMPLETE
) {
337 return NT_STATUS_INTERNAL_ERROR
;
340 if (cred_token
.length
) {
341 delegated_creds
= data_blob_talloc(req
,
344 gss_release_buffer(&minor_status
, &cred_token
);
345 NT_STATUS_HAVE_NO_MEMORY(delegated_creds
.data
);
351 subreq
= tstream_npa_connect_send(p
,
352 ipriv
->ntvfs
->ctx
->event_ctx
,
360 req
->session_info
->session_key
,
362 NT_STATUS_HAVE_NO_MEMORY(subreq
);
363 tevent_req_set_callback(subreq
, ipc_open_done
, state
);
365 req
->async_states
->state
|= NTVFS_ASYNC_STATE_ASYNC
;
369 static void ipc_open_done(struct tevent_req
*subreq
)
371 struct ipc_open_state
*state
= tevent_req_callback_data(subreq
,
372 struct ipc_open_state
);
373 struct ipc_private
*ipriv
= state
->ipriv
;
374 struct pipe_state
*p
= state
->p
;
375 struct ntvfs_request
*req
= state
->req
;
376 union smb_open
*oi
= state
->oi
;
381 ret
= tstream_npa_connect_recv(subreq
, &sys_errno
,
385 &p
->allocation_size
);
388 status
= map_nt_error_from_unix(sys_errno
);
392 DLIST_ADD(ipriv
->pipe_list
, p
);
393 talloc_set_destructor(p
, ipc_fd_destructor
);
395 status
= ntvfs_handle_set_backend_data(p
->handle
, ipriv
->ntvfs
, p
);
396 if (!NT_STATUS_IS_OK(status
)) {
400 switch (oi
->generic
.level
) {
401 case RAW_OPEN_NTCREATEX
:
402 ZERO_STRUCT(oi
->ntcreatex
.out
);
403 oi
->ntcreatex
.out
.file
.ntvfs
= p
->handle
;
404 oi
->ntcreatex
.out
.oplock_level
= 0;
405 oi
->ntcreatex
.out
.create_action
= NTCREATEX_ACTION_EXISTED
;
406 oi
->ntcreatex
.out
.create_time
= 0;
407 oi
->ntcreatex
.out
.access_time
= 0;
408 oi
->ntcreatex
.out
.write_time
= 0;
409 oi
->ntcreatex
.out
.change_time
= 0;
410 oi
->ntcreatex
.out
.attrib
= FILE_ATTRIBUTE_NORMAL
;
411 oi
->ntcreatex
.out
.alloc_size
= p
->allocation_size
;
412 oi
->ntcreatex
.out
.size
= 0;
413 oi
->ntcreatex
.out
.file_type
= p
->file_type
;
414 oi
->ntcreatex
.out
.ipc_state
= p
->device_state
;
415 oi
->ntcreatex
.out
.is_directory
= 0;
418 ZERO_STRUCT(oi
->openx
.out
);
419 oi
->openx
.out
.file
.ntvfs
= p
->handle
;
420 oi
->openx
.out
.attrib
= FILE_ATTRIBUTE_NORMAL
;
421 oi
->openx
.out
.write_time
= 0;
422 oi
->openx
.out
.size
= 0;
423 oi
->openx
.out
.access
= 0;
424 oi
->openx
.out
.ftype
= p
->file_type
;
425 oi
->openx
.out
.devstate
= p
->device_state
;
426 oi
->openx
.out
.action
= 0;
427 oi
->openx
.out
.unique_fid
= 0;
428 oi
->openx
.out
.access_mask
= 0;
429 oi
->openx
.out
.unknown
= 0;
432 ZERO_STRUCT(oi
->smb2
.out
);
433 oi
->smb2
.out
.file
.ntvfs
= p
->handle
;
434 oi
->smb2
.out
.oplock_level
= oi
->smb2
.in
.oplock_level
;
435 oi
->smb2
.out
.create_action
= NTCREATEX_ACTION_EXISTED
;
436 oi
->smb2
.out
.create_time
= 0;
437 oi
->smb2
.out
.access_time
= 0;
438 oi
->smb2
.out
.write_time
= 0;
439 oi
->smb2
.out
.change_time
= 0;
440 oi
->smb2
.out
.alloc_size
= p
->allocation_size
;
441 oi
->smb2
.out
.size
= 0;
442 oi
->smb2
.out
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
443 oi
->smb2
.out
.reserved2
= 0;
450 req
->async_states
->status
= status
;
451 req
->async_states
->send_fn(req
);
457 static NTSTATUS
ipc_mkdir(struct ntvfs_module_context
*ntvfs
,
458 struct ntvfs_request
*req
, union smb_mkdir
*md
)
460 return NT_STATUS_ACCESS_DENIED
;
466 static NTSTATUS
ipc_rmdir(struct ntvfs_module_context
*ntvfs
,
467 struct ntvfs_request
*req
, struct smb_rmdir
*rd
)
469 return NT_STATUS_ACCESS_DENIED
;
473 rename a set of files
475 static NTSTATUS
ipc_rename(struct ntvfs_module_context
*ntvfs
,
476 struct ntvfs_request
*req
, union smb_rename
*ren
)
478 return NT_STATUS_ACCESS_DENIED
;
484 static NTSTATUS
ipc_copy(struct ntvfs_module_context
*ntvfs
,
485 struct ntvfs_request
*req
, struct smb_copy
*cp
)
487 return NT_STATUS_ACCESS_DENIED
;
490 struct ipc_readv_next_vector_state
{
497 static void ipc_readv_next_vector_init(struct ipc_readv_next_vector_state
*s
,
498 uint8_t *buf
, size_t len
)
503 s
->len
= MIN(len
, UINT16_MAX
);
506 static int ipc_readv_next_vector(struct tstream_context
*stream
,
509 struct iovec
**_vector
,
512 struct ipc_readv_next_vector_state
*state
=
513 (struct ipc_readv_next_vector_state
*)private_data
;
514 struct iovec
*vector
;
518 if (state
->ofs
== state
->len
) {
524 pending
= tstream_pending_bytes(stream
);
529 if (pending
== 0 && state
->ofs
!= 0) {
530 /* return a short read */
537 /* we want at least one byte and recheck again */
540 size_t missing
= state
->len
- state
->ofs
;
541 if (pending
> missing
) {
542 /* there's more available */
543 state
->remaining
= pending
- missing
;
546 /* read what we can get and recheck in the next cycle */
551 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
556 vector
[0].iov_base
= (char *) (state
->buf
+ state
->ofs
);
557 vector
[0].iov_len
= wanted
;
559 state
->ofs
+= wanted
;
566 struct ipc_read_state
{
567 struct ipc_private
*ipriv
;
568 struct pipe_state
*p
;
569 struct ntvfs_request
*req
;
571 struct ipc_readv_next_vector_state next_vector
;
574 static void ipc_read_done(struct tevent_req
*subreq
);
579 static NTSTATUS
ipc_read(struct ntvfs_module_context
*ntvfs
,
580 struct ntvfs_request
*req
, union smb_read
*rd
)
582 struct ipc_private
*ipriv
= talloc_get_type_abort(ntvfs
->private_data
,
584 struct pipe_state
*p
;
585 struct ipc_read_state
*state
;
586 struct tevent_req
*subreq
;
588 if (rd
->generic
.level
!= RAW_READ_GENERIC
) {
589 return ntvfs_map_read(ntvfs
, req
, rd
);
592 p
= pipe_state_find(ipriv
, rd
->readx
.in
.file
.ntvfs
);
594 return NT_STATUS_INVALID_HANDLE
;
597 state
= talloc(req
, struct ipc_read_state
);
598 NT_STATUS_HAVE_NO_MEMORY(state
);
600 state
->ipriv
= ipriv
;
605 /* rd->readx.out.data is already allocated */
606 ipc_readv_next_vector_init(&state
->next_vector
,
608 rd
->readx
.in
.maxcnt
);
610 subreq
= tstream_readv_pdu_queue_send(req
,
611 ipriv
->ntvfs
->ctx
->event_ctx
,
614 ipc_readv_next_vector
,
615 &state
->next_vector
);
616 NT_STATUS_HAVE_NO_MEMORY(subreq
);
617 tevent_req_set_callback(subreq
, ipc_read_done
, state
);
619 req
->async_states
->state
|= NTVFS_ASYNC_STATE_ASYNC
;
623 static void ipc_read_done(struct tevent_req
*subreq
)
625 struct ipc_read_state
*state
=
626 tevent_req_callback_data(subreq
,
627 struct ipc_read_state
);
628 struct ntvfs_request
*req
= state
->req
;
629 union smb_read
*rd
= state
->rd
;
634 ret
= tstream_readv_pdu_queue_recv(subreq
, &sys_errno
);
637 status
= map_nt_error_from_unix(sys_errno
);
641 status
= NT_STATUS_OK
;
642 if (state
->next_vector
.remaining
> 0) {
643 status
= STATUS_BUFFER_OVERFLOW
;
646 rd
->readx
.out
.remaining
= state
->next_vector
.remaining
;
647 rd
->readx
.out
.compaction_mode
= 0;
648 rd
->readx
.out
.nread
= ret
;
651 req
->async_states
->status
= status
;
652 req
->async_states
->send_fn(req
);
655 struct ipc_write_state
{
656 struct ipc_private
*ipriv
;
657 struct pipe_state
*p
;
658 struct ntvfs_request
*req
;
663 static void ipc_write_done(struct tevent_req
*subreq
);
668 static NTSTATUS
ipc_write(struct ntvfs_module_context
*ntvfs
,
669 struct ntvfs_request
*req
, union smb_write
*wr
)
671 struct ipc_private
*ipriv
= talloc_get_type_abort(ntvfs
->private_data
,
673 struct pipe_state
*p
;
674 struct tevent_req
*subreq
;
675 struct ipc_write_state
*state
;
677 if (wr
->generic
.level
!= RAW_WRITE_GENERIC
) {
678 return ntvfs_map_write(ntvfs
, req
, wr
);
681 p
= pipe_state_find(ipriv
, wr
->writex
.in
.file
.ntvfs
);
683 return NT_STATUS_INVALID_HANDLE
;
686 state
= talloc(req
, struct ipc_write_state
);
687 NT_STATUS_HAVE_NO_MEMORY(state
);
689 state
->ipriv
= ipriv
;
693 state
->iov
.iov_base
= discard_const_p(void, wr
->writex
.in
.data
);
694 state
->iov
.iov_len
= wr
->writex
.in
.count
;
696 subreq
= tstream_writev_queue_send(state
,
697 ipriv
->ntvfs
->ctx
->event_ctx
,
701 NT_STATUS_HAVE_NO_MEMORY(subreq
);
702 tevent_req_set_callback(subreq
, ipc_write_done
, state
);
704 req
->async_states
->state
|= NTVFS_ASYNC_STATE_ASYNC
;
708 static void ipc_write_done(struct tevent_req
*subreq
)
710 struct ipc_write_state
*state
=
711 tevent_req_callback_data(subreq
,
712 struct ipc_write_state
);
713 struct ntvfs_request
*req
= state
->req
;
714 union smb_write
*wr
= state
->wr
;
719 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
722 status
= map_nt_error_from_unix(sys_errno
);
726 status
= NT_STATUS_OK
;
728 wr
->writex
.out
.nwritten
= ret
;
729 wr
->writex
.out
.remaining
= 0;
732 req
->async_states
->status
= status
;
733 req
->async_states
->send_fn(req
);
739 static NTSTATUS
ipc_seek(struct ntvfs_module_context
*ntvfs
,
740 struct ntvfs_request
*req
,
743 return NT_STATUS_ACCESS_DENIED
;
749 static NTSTATUS
ipc_flush(struct ntvfs_module_context
*ntvfs
,
750 struct ntvfs_request
*req
,
753 return NT_STATUS_ACCESS_DENIED
;
759 static NTSTATUS
ipc_close(struct ntvfs_module_context
*ntvfs
,
760 struct ntvfs_request
*req
, union smb_close
*io
)
762 struct ipc_private
*ipriv
= talloc_get_type_abort(ntvfs
->private_data
,
764 struct pipe_state
*p
;
766 if (io
->generic
.level
!= RAW_CLOSE_CLOSE
) {
767 return ntvfs_map_close(ntvfs
, req
, io
);
770 p
= pipe_state_find(ipriv
, io
->close
.in
.file
.ntvfs
);
772 return NT_STATUS_INVALID_HANDLE
;
783 static NTSTATUS
ipc_exit(struct ntvfs_module_context
*ntvfs
,
784 struct ntvfs_request
*req
)
786 struct ipc_private
*ipriv
= talloc_get_type_abort(ntvfs
->private_data
,
788 struct pipe_state
*p
, *next
;
790 for (p
=ipriv
->pipe_list
; p
; p
=next
) {
792 if (p
->handle
->session_info
== req
->session_info
&&
793 p
->handle
->smbpid
== req
->smbpid
) {
802 logoff - closing files open by the user
804 static NTSTATUS
ipc_logoff(struct ntvfs_module_context
*ntvfs
,
805 struct ntvfs_request
*req
)
807 struct ipc_private
*ipriv
= talloc_get_type_abort(ntvfs
->private_data
,
809 struct pipe_state
*p
, *next
;
811 for (p
=ipriv
->pipe_list
; p
; p
=next
) {
813 if (p
->handle
->session_info
== req
->session_info
) {
822 setup for an async call
824 static NTSTATUS
ipc_async_setup(struct ntvfs_module_context
*ntvfs
,
825 struct ntvfs_request
*req
,
834 static NTSTATUS
ipc_cancel(struct ntvfs_module_context
*ntvfs
,
835 struct ntvfs_request
*req
)
837 return NT_STATUS_UNSUCCESSFUL
;
843 static NTSTATUS
ipc_lock(struct ntvfs_module_context
*ntvfs
,
844 struct ntvfs_request
*req
, union smb_lock
*lck
)
846 return NT_STATUS_ACCESS_DENIED
;
850 set info on a open file
852 static NTSTATUS
ipc_setfileinfo(struct ntvfs_module_context
*ntvfs
,
853 struct ntvfs_request
*req
, union smb_setfileinfo
*info
)
855 return NT_STATUS_ACCESS_DENIED
;
859 query info on a open file
861 static NTSTATUS
ipc_qfileinfo(struct ntvfs_module_context
*ntvfs
,
862 struct ntvfs_request
*req
, union smb_fileinfo
*info
)
864 struct ipc_private
*ipriv
= talloc_get_type_abort(ntvfs
->private_data
,
866 struct pipe_state
*p
= pipe_state_find(ipriv
, info
->generic
.in
.file
.ntvfs
);
868 return NT_STATUS_INVALID_HANDLE
;
870 switch (info
->generic
.level
) {
871 case RAW_FILEINFO_GENERIC
:
873 ZERO_STRUCT(info
->generic
.out
);
874 info
->generic
.out
.attrib
= FILE_ATTRIBUTE_NORMAL
;
875 info
->generic
.out
.fname
.s
= strrchr(p
->pipe_name
, '\\');
876 info
->generic
.out
.alloc_size
= 4096;
877 info
->generic
.out
.nlink
= 1;
878 /* What the heck? Match Win2k3: IPC$ pipes are delete pending */
879 info
->generic
.out
.delete_pending
= 1;
882 case RAW_FILEINFO_ALT_NAME_INFO
:
883 case RAW_FILEINFO_ALT_NAME_INFORMATION
:
884 case RAW_FILEINFO_STREAM_INFO
:
885 case RAW_FILEINFO_STREAM_INFORMATION
:
886 case RAW_FILEINFO_COMPRESSION_INFO
:
887 case RAW_FILEINFO_COMPRESSION_INFORMATION
:
888 case RAW_FILEINFO_NETWORK_OPEN_INFORMATION
:
889 case RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION
:
890 return NT_STATUS_INVALID_PARAMETER
;
891 case RAW_FILEINFO_ALL_EAS
:
892 return NT_STATUS_ACCESS_DENIED
;
894 return ntvfs_map_qfileinfo(ntvfs
, req
, info
);
900 return filesystem info
902 static NTSTATUS
ipc_fsinfo(struct ntvfs_module_context
*ntvfs
,
903 struct ntvfs_request
*req
, union smb_fsinfo
*fs
)
905 return NT_STATUS_ACCESS_DENIED
;
909 return print queue info
911 static NTSTATUS
ipc_lpq(struct ntvfs_module_context
*ntvfs
,
912 struct ntvfs_request
*req
, union smb_lpq
*lpq
)
914 return NT_STATUS_ACCESS_DENIED
;
918 list files in a directory matching a wildcard pattern
920 static NTSTATUS
ipc_search_first(struct ntvfs_module_context
*ntvfs
,
921 struct ntvfs_request
*req
, union smb_search_first
*io
,
922 void *search_private
,
923 bool (*callback
)(void *, const union smb_search_data
*))
925 return NT_STATUS_ACCESS_DENIED
;
929 continue listing files in a directory
931 static NTSTATUS
ipc_search_next(struct ntvfs_module_context
*ntvfs
,
932 struct ntvfs_request
*req
, union smb_search_next
*io
,
933 void *search_private
,
934 bool (*callback
)(void *, const union smb_search_data
*))
936 return NT_STATUS_ACCESS_DENIED
;
940 end listing files in a directory
942 static NTSTATUS
ipc_search_close(struct ntvfs_module_context
*ntvfs
,
943 struct ntvfs_request
*req
, union smb_search_close
*io
)
945 return NT_STATUS_ACCESS_DENIED
;
948 struct ipc_trans_state
{
949 struct ipc_private
*ipriv
;
950 struct pipe_state
*p
;
951 struct ntvfs_request
*req
;
952 struct smb_trans2
*trans
;
953 struct iovec writev_iov
;
954 struct ipc_readv_next_vector_state next_vector
;
957 static void ipc_trans_writev_done(struct tevent_req
*subreq
);
958 static void ipc_trans_readv_done(struct tevent_req
*subreq
);
960 /* SMBtrans - handle a DCERPC command */
961 static NTSTATUS
ipc_dcerpc_cmd(struct ntvfs_module_context
*ntvfs
,
962 struct ntvfs_request
*req
, struct smb_trans2
*trans
)
964 struct ipc_private
*ipriv
= talloc_get_type_abort(ntvfs
->private_data
,
966 struct pipe_state
*p
;
969 struct ipc_trans_state
*state
;
970 struct tevent_req
*subreq
;
973 * the fnum is in setup[1], a 16 bit value
974 * the setup[*] values are already in host byteorder
975 * but ntvfs_handle_search_by_wire_key() expects
978 SSVAL(&fnum
, 0, trans
->in
.setup
[1]);
979 fnum_key
= data_blob_const(&fnum
, 2);
981 p
= pipe_state_find_key(ipriv
, req
, &fnum_key
);
983 return NT_STATUS_INVALID_HANDLE
;
987 * Trans requests are only allowed
988 * if no other Trans or Read is active
990 if (tevent_queue_length(p
->read_queue
) > 0) {
991 return NT_STATUS_PIPE_BUSY
;
994 state
= talloc(req
, struct ipc_trans_state
);
995 NT_STATUS_HAVE_NO_MEMORY(state
);
997 trans
->out
.setup_count
= 0;
998 trans
->out
.setup
= NULL
;
999 trans
->out
.params
= data_blob(NULL
, 0);
1000 trans
->out
.data
= data_blob_talloc(req
, NULL
, trans
->in
.max_data
);
1001 NT_STATUS_HAVE_NO_MEMORY(trans
->out
.data
.data
);
1003 state
->ipriv
= ipriv
;
1006 state
->trans
= trans
;
1007 state
->writev_iov
.iov_base
= (char *) trans
->in
.data
.data
;
1008 state
->writev_iov
.iov_len
= trans
->in
.data
.length
;
1010 ipc_readv_next_vector_init(&state
->next_vector
,
1011 trans
->out
.data
.data
,
1012 trans
->out
.data
.length
);
1014 subreq
= tstream_writev_queue_send(state
,
1015 ipriv
->ntvfs
->ctx
->event_ctx
,
1018 &state
->writev_iov
, 1);
1019 NT_STATUS_HAVE_NO_MEMORY(subreq
);
1020 tevent_req_set_callback(subreq
, ipc_trans_writev_done
, state
);
1022 req
->async_states
->state
|= NTVFS_ASYNC_STATE_ASYNC
;
1023 return NT_STATUS_OK
;
1026 static void ipc_trans_writev_done(struct tevent_req
*subreq
)
1028 struct ipc_trans_state
*state
=
1029 tevent_req_callback_data(subreq
,
1030 struct ipc_trans_state
);
1031 struct ipc_private
*ipriv
= state
->ipriv
;
1032 struct pipe_state
*p
= state
->p
;
1033 struct ntvfs_request
*req
= state
->req
;
1038 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
1039 TALLOC_FREE(subreq
);
1041 status
= NT_STATUS_PIPE_DISCONNECTED
;
1043 } else if (ret
== -1) {
1044 status
= map_nt_error_from_unix(sys_errno
);
1048 subreq
= tstream_readv_pdu_queue_send(state
,
1049 ipriv
->ntvfs
->ctx
->event_ctx
,
1052 ipc_readv_next_vector
,
1053 &state
->next_vector
);
1055 status
= NT_STATUS_NO_MEMORY
;
1058 tevent_req_set_callback(subreq
, ipc_trans_readv_done
, state
);
1062 req
->async_states
->status
= status
;
1063 req
->async_states
->send_fn(req
);
1066 static void ipc_trans_readv_done(struct tevent_req
*subreq
)
1068 struct ipc_trans_state
*state
=
1069 tevent_req_callback_data(subreq
,
1070 struct ipc_trans_state
);
1071 struct ntvfs_request
*req
= state
->req
;
1072 struct smb_trans2
*trans
= state
->trans
;
1077 ret
= tstream_readv_pdu_queue_recv(subreq
, &sys_errno
);
1078 TALLOC_FREE(subreq
);
1080 status
= map_nt_error_from_unix(sys_errno
);
1084 status
= NT_STATUS_OK
;
1085 if (state
->next_vector
.remaining
> 0) {
1086 status
= STATUS_BUFFER_OVERFLOW
;
1089 trans
->out
.data
.length
= ret
;
1092 req
->async_states
->status
= status
;
1093 req
->async_states
->send_fn(req
);
1096 /* SMBtrans - set named pipe state */
1097 static NTSTATUS
ipc_set_nm_pipe_state(struct ntvfs_module_context
*ntvfs
,
1098 struct ntvfs_request
*req
, struct smb_trans2
*trans
)
1100 struct ipc_private
*ipriv
= talloc_get_type_abort(ntvfs
->private_data
,
1101 struct ipc_private
);
1102 struct pipe_state
*p
;
1105 /* the fnum is in setup[1] */
1106 fnum_key
= data_blob_const(&trans
->in
.setup
[1], sizeof(trans
->in
.setup
[1]));
1108 p
= pipe_state_find_key(ipriv
, req
, &fnum_key
);
1110 return NT_STATUS_INVALID_HANDLE
;
1113 if (trans
->in
.params
.length
!= 2) {
1114 return NT_STATUS_INVALID_PARAMETER
;
1118 * TODO: pass this to the tstream_npa logic
1120 p
->device_state
= SVAL(trans
->in
.params
.data
, 0);
1122 trans
->out
.setup_count
= 0;
1123 trans
->out
.setup
= NULL
;
1124 trans
->out
.params
= data_blob(NULL
, 0);
1125 trans
->out
.data
= data_blob(NULL
, 0);
1127 return NT_STATUS_OK
;
1131 /* SMBtrans - used to provide access to SMB pipes */
1132 static NTSTATUS
ipc_trans(struct ntvfs_module_context
*ntvfs
,
1133 struct ntvfs_request
*req
, struct smb_trans2
*trans
)
1137 if (strequal(trans
->in
.trans_name
, "\\PIPE\\LANMAN"))
1138 return ipc_rap_call(req
, ntvfs
->ctx
->event_ctx
, ntvfs
->ctx
->lp_ctx
, trans
);
1140 if (trans
->in
.setup_count
!= 2) {
1141 return NT_STATUS_INVALID_PARAMETER
;
1144 switch (trans
->in
.setup
[0]) {
1145 case TRANSACT_SETNAMEDPIPEHANDLESTATE
:
1146 status
= ipc_set_nm_pipe_state(ntvfs
, req
, trans
);
1148 case TRANSACT_DCERPCCMD
:
1149 status
= ipc_dcerpc_cmd(ntvfs
, req
, trans
);
1152 status
= NT_STATUS_INVALID_PARAMETER
;
1159 struct ipc_ioctl_state
{
1160 struct ipc_private
*ipriv
;
1161 struct pipe_state
*p
;
1162 struct ntvfs_request
*req
;
1163 union smb_ioctl
*io
;
1164 struct iovec writev_iov
;
1165 struct ipc_readv_next_vector_state next_vector
;
1168 static void ipc_ioctl_writev_done(struct tevent_req
*subreq
);
1169 static void ipc_ioctl_readv_done(struct tevent_req
*subreq
);
1171 static NTSTATUS
ipc_ioctl_smb2(struct ntvfs_module_context
*ntvfs
,
1172 struct ntvfs_request
*req
, union smb_ioctl
*io
)
1174 struct ipc_private
*ipriv
= talloc_get_type_abort(ntvfs
->private_data
,
1175 struct ipc_private
);
1176 struct pipe_state
*p
;
1177 struct ipc_ioctl_state
*state
;
1178 struct tevent_req
*subreq
;
1180 switch (io
->smb2
.in
.function
) {
1181 case FSCTL_NAMED_PIPE_READ_WRITE
:
1185 return NT_STATUS_FS_DRIVER_REQUIRED
;
1188 p
= pipe_state_find(ipriv
, io
->smb2
.in
.file
.ntvfs
);
1190 return NT_STATUS_INVALID_HANDLE
;
1194 * Trans requests are only allowed
1195 * if no other Trans or Read is active
1197 if (tevent_queue_length(p
->read_queue
) > 0) {
1198 return NT_STATUS_PIPE_BUSY
;
1201 state
= talloc(req
, struct ipc_ioctl_state
);
1202 NT_STATUS_HAVE_NO_MEMORY(state
);
1204 io
->smb2
.out
._pad
= 0;
1205 io
->smb2
.out
.function
= io
->smb2
.in
.function
;
1206 io
->smb2
.out
.unknown2
= 0;
1207 io
->smb2
.out
.unknown3
= 0;
1208 io
->smb2
.out
.in
= io
->smb2
.in
.out
;
1209 io
->smb2
.out
.out
= data_blob_talloc(req
, NULL
, io
->smb2
.in
.max_response_size
);
1210 NT_STATUS_HAVE_NO_MEMORY(io
->smb2
.out
.out
.data
);
1212 state
->ipriv
= ipriv
;
1216 state
->writev_iov
.iov_base
= (char *) io
->smb2
.in
.out
.data
;
1217 state
->writev_iov
.iov_len
= io
->smb2
.in
.out
.length
;
1219 ipc_readv_next_vector_init(&state
->next_vector
,
1220 io
->smb2
.out
.out
.data
,
1221 io
->smb2
.out
.out
.length
);
1223 subreq
= tstream_writev_queue_send(state
,
1224 ipriv
->ntvfs
->ctx
->event_ctx
,
1227 &state
->writev_iov
, 1);
1228 NT_STATUS_HAVE_NO_MEMORY(subreq
);
1229 tevent_req_set_callback(subreq
, ipc_ioctl_writev_done
, state
);
1231 req
->async_states
->state
|= NTVFS_ASYNC_STATE_ASYNC
;
1232 return NT_STATUS_OK
;
1235 static void ipc_ioctl_writev_done(struct tevent_req
*subreq
)
1237 struct ipc_ioctl_state
*state
=
1238 tevent_req_callback_data(subreq
,
1239 struct ipc_ioctl_state
);
1240 struct ipc_private
*ipriv
= state
->ipriv
;
1241 struct pipe_state
*p
= state
->p
;
1242 struct ntvfs_request
*req
= state
->req
;
1247 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
1248 TALLOC_FREE(subreq
);
1250 status
= map_nt_error_from_unix(sys_errno
);
1254 subreq
= tstream_readv_pdu_queue_send(state
,
1255 ipriv
->ntvfs
->ctx
->event_ctx
,
1258 ipc_readv_next_vector
,
1259 &state
->next_vector
);
1261 status
= NT_STATUS_NO_MEMORY
;
1264 tevent_req_set_callback(subreq
, ipc_ioctl_readv_done
, state
);
1268 req
->async_states
->status
= status
;
1269 req
->async_states
->send_fn(req
);
1272 static void ipc_ioctl_readv_done(struct tevent_req
*subreq
)
1274 struct ipc_ioctl_state
*state
=
1275 tevent_req_callback_data(subreq
,
1276 struct ipc_ioctl_state
);
1277 struct ntvfs_request
*req
= state
->req
;
1278 union smb_ioctl
*io
= state
->io
;
1283 ret
= tstream_readv_pdu_queue_recv(subreq
, &sys_errno
);
1284 TALLOC_FREE(subreq
);
1286 status
= map_nt_error_from_unix(sys_errno
);
1290 status
= NT_STATUS_OK
;
1291 if (state
->next_vector
.remaining
> 0) {
1292 status
= STATUS_BUFFER_OVERFLOW
;
1295 io
->smb2
.out
.out
.length
= ret
;
1298 req
->async_states
->status
= status
;
1299 req
->async_states
->send_fn(req
);
1305 static NTSTATUS
ipc_ioctl(struct ntvfs_module_context
*ntvfs
,
1306 struct ntvfs_request
*req
, union smb_ioctl
*io
)
1308 switch (io
->generic
.level
) {
1309 case RAW_IOCTL_SMB2
:
1310 return ipc_ioctl_smb2(ntvfs
, req
, io
);
1312 case RAW_IOCTL_SMB2_NO_HANDLE
:
1313 return NT_STATUS_FS_DRIVER_REQUIRED
;
1316 return NT_STATUS_ACCESS_DENIED
;
1322 initialialise the IPC backend, registering ourselves with the ntvfs subsystem
1324 NTSTATUS
ntvfs_ipc_init(void)
1327 struct ntvfs_ops ops
;
1328 NTVFS_CURRENT_CRITICAL_SIZES(vers
);
1332 /* fill in the name and type */
1333 ops
.name
= "default";
1334 ops
.type
= NTVFS_IPC
;
1336 /* fill in all the operations */
1337 ops
.connect
= ipc_connect
;
1338 ops
.disconnect
= ipc_disconnect
;
1339 ops
.unlink
= ipc_unlink
;
1340 ops
.chkpath
= ipc_chkpath
;
1341 ops
.qpathinfo
= ipc_qpathinfo
;
1342 ops
.setpathinfo
= ipc_setpathinfo
;
1343 ops
.open
= ipc_open
;
1344 ops
.mkdir
= ipc_mkdir
;
1345 ops
.rmdir
= ipc_rmdir
;
1346 ops
.rename
= ipc_rename
;
1347 ops
.copy
= ipc_copy
;
1348 ops
.ioctl
= ipc_ioctl
;
1349 ops
.read
= ipc_read
;
1350 ops
.write
= ipc_write
;
1351 ops
.seek
= ipc_seek
;
1352 ops
.flush
= ipc_flush
;
1353 ops
.close
= ipc_close
;
1354 ops
.exit
= ipc_exit
;
1355 ops
.lock
= ipc_lock
;
1356 ops
.setfileinfo
= ipc_setfileinfo
;
1357 ops
.qfileinfo
= ipc_qfileinfo
;
1358 ops
.fsinfo
= ipc_fsinfo
;
1360 ops
.search_first
= ipc_search_first
;
1361 ops
.search_next
= ipc_search_next
;
1362 ops
.search_close
= ipc_search_close
;
1363 ops
.trans
= ipc_trans
;
1364 ops
.logoff
= ipc_logoff
;
1365 ops
.async_setup
= ipc_async_setup
;
1366 ops
.cancel
= ipc_cancel
;
1368 /* register ourselves with the NTVFS subsystem. */
1369 ret
= ntvfs_register(&ops
, &vers
);
1371 if (!NT_STATUS_IS_OK(ret
)) {
1372 DEBUG(0,("Failed to register IPC backend!\n"));