pyldb: avoid segfault when adding an element with no name
[kai/samba-autobuild/.git] / source4 / ntvfs / ipc / vfs_ipc.c
1 /* 
2    Unix SMB/CIFS implementation.
3    default IPC$ NTVFS backend
4
5    Copyright (C) Andrew Tridgell 2003
6    Copyright (C) Stefan (metze) Metzmacher 2004-2005
7
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.
12    
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.
17    
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/>.
20 */
21 /*
22   this implements the IPC$ backend, called by the NTVFS subsystem to
23   handle requests on IPC$ shares
24 */
25
26
27 #include "includes.h"
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"
45
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
48    pipes */
49 struct ipc_private {
50         struct ntvfs_module_context *ntvfs;
51
52         /* a list of open pipes */
53         struct pipe_state {
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;
59                 uint16_t file_type;
60                 uint16_t device_state;
61                 uint64_t allocation_size;
62                 struct tevent_queue *write_queue;
63                 struct tevent_queue *read_queue;
64         } *pipe_list;
65 };
66
67
68 /*
69   find a open pipe give a file handle
70 */
71 static struct pipe_state *pipe_state_find(struct ipc_private *ipriv, struct ntvfs_handle *handle)
72 {
73         struct pipe_state *s;
74         void *p;
75
76         p = ntvfs_handle_get_backend_data(handle, ipriv->ntvfs);
77         if (!p) return NULL;
78
79         s = talloc_get_type(p, struct pipe_state);
80         if (!s) return NULL;
81
82         return s;
83 }
84
85 /*
86   find a open pipe give a wire fnum
87 */
88 static struct pipe_state *pipe_state_find_key(struct ipc_private *ipriv, struct ntvfs_request *req, const DATA_BLOB *key)
89 {
90         struct ntvfs_handle *h;
91
92         h = ntvfs_handle_search_by_wire_key(ipriv->ntvfs, req, key);
93         if (!h) return NULL;
94
95         return pipe_state_find(ipriv, h);
96 }
97
98
99 /*
100   connect to a share - always works 
101 */
102 static NTSTATUS ipc_connect(struct ntvfs_module_context *ntvfs,
103                             struct ntvfs_request *req,
104                             union smb_tcon* tcon)
105 {
106         struct ipc_private *ipriv;
107         const char *sharename;
108
109         switch (tcon->generic.level) {
110         case RAW_TCON_TCON:
111                 sharename = tcon->tcon.in.service;
112                 break;
113         case RAW_TCON_TCONX:
114                 sharename = tcon->tconx.in.path;
115                 break;
116         case RAW_TCON_SMB2:
117                 sharename = tcon->smb2.in.path;
118                 break;
119         default:
120                 return NT_STATUS_INVALID_LEVEL;
121         }
122
123         if (strncmp(sharename, "\\\\", 2) == 0) {
124                 char *p = strchr(sharename+2, '\\');
125                 if (p) {
126                         sharename = p + 1;
127                 }
128         }
129
130         ntvfs->ctx->fs_type = talloc_strdup(ntvfs->ctx, "IPC");
131         NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->fs_type);
132
133         ntvfs->ctx->dev_type = talloc_strdup(ntvfs->ctx, "IPC");
134         NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->dev_type);
135
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;
139         }
140
141         /* prepare the private state for this connection */
142         ipriv = talloc(ntvfs, struct ipc_private);
143         NT_STATUS_HAVE_NO_MEMORY(ipriv);
144
145         ntvfs->private_data = ipriv;
146
147         ipriv->ntvfs = ntvfs;
148         ipriv->pipe_list = NULL;
149
150         return NT_STATUS_OK;
151 }
152
153 /*
154   disconnect from a share
155 */
156 static NTSTATUS ipc_disconnect(struct ntvfs_module_context *ntvfs)
157 {
158         return NT_STATUS_OK;
159 }
160
161 /*
162   delete a file
163 */
164 static NTSTATUS ipc_unlink(struct ntvfs_module_context *ntvfs,
165                            struct ntvfs_request *req,
166                            union smb_unlink *unl)
167 {
168         return NT_STATUS_ACCESS_DENIED;
169 }
170
171 /*
172   check if a directory exists
173 */
174 static NTSTATUS ipc_chkpath(struct ntvfs_module_context *ntvfs,
175                             struct ntvfs_request *req,
176                             union smb_chkpath *cp)
177 {
178         return NT_STATUS_ACCESS_DENIED;
179 }
180
181 /*
182   return info on a pathname
183 */
184 static NTSTATUS ipc_qpathinfo(struct ntvfs_module_context *ntvfs,
185                               struct ntvfs_request *req, union smb_fileinfo *info)
186 {
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;
192         default:
193                 return ntvfs_map_qpathinfo(ntvfs, req, info);
194         }
195 }
196
197 /*
198   set info on a pathname
199 */
200 static NTSTATUS ipc_setpathinfo(struct ntvfs_module_context *ntvfs,
201                                 struct ntvfs_request *req, union smb_setfileinfo *st)
202 {
203         return NT_STATUS_ACCESS_DENIED;
204 }
205
206
207 /*
208   destroy a open pipe structure
209 */
210 static int ipc_fd_destructor(struct pipe_state *p)
211 {
212         DLIST_REMOVE(p->ipriv->pipe_list, p);
213         ntvfs_handle_remove_backend_data(p->handle, p->ipriv->ntvfs);
214         return 0;
215 }
216
217 struct ipc_open_state {
218         struct ipc_private *ipriv;
219         struct pipe_state *p;
220         struct ntvfs_request *req;
221         union smb_open *oi;
222         struct auth_session_info_transport *session_info_transport;
223 };
224
225 static void ipc_open_done(struct tevent_req *subreq);
226
227 /*
228   check the pipename is valid
229  */
230 static NTSTATUS validate_pipename(const char *name)
231 {
232         while (*name) {
233                 if (!isalnum(*name) && *name != '_') {
234                         return NT_STATUS_INVALID_PARAMETER;
235                 }
236                 name++;
237         }
238         return NT_STATUS_OK;
239 }
240
241 /*
242   open a file - used for MSRPC pipes
243 */
244 static NTSTATUS ipc_open(struct ntvfs_module_context *ntvfs,
245                          struct ntvfs_request *req, union smb_open *oi)
246 {
247         NTSTATUS status;
248         struct pipe_state *p;
249         struct ipc_private *ipriv = talloc_get_type_abort(ntvfs->private_data,
250                                     struct ipc_private);
251         struct ntvfs_handle *h;
252         struct ipc_open_state *state;
253         struct tevent_req *subreq;
254         const char *fname;
255         const char *directory;
256         const struct tsocket_address *remote_client_addr;
257         const struct tsocket_address *local_server_addr;
258
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++;
264                 break;
265         case RAW_OPEN_OPENX:
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;
270                 }
271                 while (fname[0] == '\\') fname++;
272                 break;
273         case RAW_OPEN_SMB2:
274                 fname = oi->smb2.in.fname;
275                 break;
276         default:
277                 return NT_STATUS_NOT_SUPPORTED;
278         }
279
280         directory = talloc_asprintf(req, "%s/np",
281                                     lpcfg_ncalrpc_dir(ipriv->ntvfs->ctx->lp_ctx));
282         NT_STATUS_HAVE_NO_MEMORY(directory);
283
284         state = talloc(req, struct ipc_open_state);
285         NT_STATUS_HAVE_NO_MEMORY(state);
286
287         status = ntvfs_handle_new(ntvfs, req, &h);
288         NT_STATUS_NOT_OK_RETURN(status);
289
290         p = talloc(h, struct pipe_state);
291         NT_STATUS_HAVE_NO_MEMORY(p);
292
293         /* check for valid characters in name */
294         fname = strlower_talloc(p, fname);
295
296         status = validate_pipename(fname);
297         NT_STATUS_NOT_OK_RETURN(status);
298
299         p->pipe_name = talloc_asprintf(p, "\\pipe\\%s", fname);
300         NT_STATUS_HAVE_NO_MEMORY(p->pipe_name);
301
302         p->handle = h;
303         p->ipriv = ipriv;
304
305         p->write_queue = tevent_queue_create(p, "ipc_write_queue");
306         NT_STATUS_HAVE_NO_MEMORY(p->write_queue);
307
308         p->read_queue = tevent_queue_create(p, "ipc_read_queue");
309         NT_STATUS_HAVE_NO_MEMORY(p->read_queue);
310
311         state->ipriv = ipriv;
312         state->p = p;
313         state->req = req;
314         state->oi = oi;
315
316         status = auth_session_info_transport_from_session(state,
317                                                           req->session_info,
318                                                           ipriv->ntvfs->ctx->event_ctx,
319                                                           ipriv->ntvfs->ctx->lp_ctx,
320                                                           &state->session_info_transport);
321
322         NT_STATUS_NOT_OK_RETURN(status);
323
324         local_server_addr = ntvfs_get_local_address(ipriv->ntvfs);
325         remote_client_addr = ntvfs_get_remote_address(ipriv->ntvfs);
326
327         subreq = tstream_npa_connect_send(p,
328                                           ipriv->ntvfs->ctx->event_ctx,
329                                           directory,
330                                           fname,
331                                           remote_client_addr,
332                                           NULL,
333                                           local_server_addr,
334                                           NULL,
335                                           state->session_info_transport);
336         NT_STATUS_HAVE_NO_MEMORY(subreq);
337         tevent_req_set_callback(subreq, ipc_open_done, state);
338
339         req->async_states->state |= NTVFS_ASYNC_STATE_ASYNC;
340         return NT_STATUS_OK;
341 }
342
343 static void ipc_open_done(struct tevent_req *subreq)
344 {
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;
351         int ret;
352         int sys_errno;
353         NTSTATUS status;
354
355         ret = tstream_npa_connect_recv(subreq, &sys_errno,
356                                        p, &p->npipe,
357                                        &p->file_type,
358                                        &p->device_state,
359                                        &p->allocation_size);
360         TALLOC_FREE(subreq);
361         if (ret == -1) {
362                 status = map_nt_error_from_unix_common(sys_errno);
363                 goto reply;
364         }
365
366         DLIST_ADD(ipriv->pipe_list, p);
367         talloc_set_destructor(p, ipc_fd_destructor);
368
369         status = ntvfs_handle_set_backend_data(p->handle, ipriv->ntvfs, p);
370         if (!NT_STATUS_IS_OK(status)) {
371                 goto reply;
372         }
373
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;
390                 break;
391         case RAW_OPEN_OPENX:
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;
404                 break;
405         case RAW_OPEN_SMB2:
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;
418                 break;
419         default:
420                 break;
421         }
422
423 reply:
424         req->async_states->status = status;
425         req->async_states->send_fn(req);
426 }
427
428 /*
429   create a directory
430 */
431 static NTSTATUS ipc_mkdir(struct ntvfs_module_context *ntvfs,
432                           struct ntvfs_request *req, union smb_mkdir *md)
433 {
434         return NT_STATUS_ACCESS_DENIED;
435 }
436
437 /*
438   remove a directory
439 */
440 static NTSTATUS ipc_rmdir(struct ntvfs_module_context *ntvfs,
441                           struct ntvfs_request *req, struct smb_rmdir *rd)
442 {
443         return NT_STATUS_ACCESS_DENIED;
444 }
445
446 /*
447   rename a set of files
448 */
449 static NTSTATUS ipc_rename(struct ntvfs_module_context *ntvfs,
450                            struct ntvfs_request *req, union smb_rename *ren)
451 {
452         return NT_STATUS_ACCESS_DENIED;
453 }
454
455 /*
456   copy a set of files
457 */
458 static NTSTATUS ipc_copy(struct ntvfs_module_context *ntvfs,
459                          struct ntvfs_request *req, struct smb_copy *cp)
460 {
461         return NT_STATUS_ACCESS_DENIED;
462 }
463
464 struct ipc_readv_next_vector_state {
465         uint8_t *buf;
466         size_t len;
467         off_t ofs;
468         size_t remaining;
469 };
470
471 static void ipc_readv_next_vector_init(struct ipc_readv_next_vector_state *s,
472                                        uint8_t *buf, size_t len)
473 {
474         ZERO_STRUCTP(s);
475
476         s->buf = buf;
477         s->len = MIN(len, UINT16_MAX);
478 }
479
480 static int ipc_readv_next_vector(struct tstream_context *stream,
481                                  void *private_data,
482                                  TALLOC_CTX *mem_ctx,
483                                  struct iovec **_vector,
484                                  size_t *count)
485 {
486         struct ipc_readv_next_vector_state *state =
487                 (struct ipc_readv_next_vector_state *)private_data;
488         struct iovec *vector;
489         ssize_t pending;
490         size_t wanted;
491
492         if (state->ofs == state->len) {
493                 *_vector = NULL;
494                 *count = 0;
495                 return 0;
496         }
497
498         pending = tstream_pending_bytes(stream);
499         if (pending == -1) {
500                 return -1;
501         }
502
503         if (pending == 0 && state->ofs != 0) {
504                 /* return a short read */
505                 *_vector = NULL;
506                 *count = 0;
507                 return 0;
508         }
509
510         if (pending == 0) {
511                 /* we want at least one byte and recheck again */
512                 wanted = 1;
513         } else {
514                 size_t missing = state->len - state->ofs;
515                 if (pending > missing) {
516                         /* there's more available */
517                         state->remaining = pending - missing;
518                         wanted = missing;
519                 } else {
520                         /* read what we can get and recheck in the next cycle */
521                         wanted = pending;
522                 }
523         }
524
525         vector = talloc_array(mem_ctx, struct iovec, 1);
526         if (!vector) {
527                 return -1;
528         }
529
530         vector[0].iov_base = (char *) (state->buf + state->ofs);
531         vector[0].iov_len = wanted;
532
533         state->ofs += wanted;
534
535         *_vector = vector;
536         *count = 1;
537         return 0;
538 }
539
540 struct ipc_read_state {
541         struct ipc_private *ipriv;
542         struct pipe_state *p;
543         struct ntvfs_request *req;
544         union smb_read *rd;
545         struct ipc_readv_next_vector_state next_vector;
546 };
547
548 static void ipc_read_done(struct tevent_req *subreq);
549
550 /*
551   read from a file
552 */
553 static NTSTATUS ipc_read(struct ntvfs_module_context *ntvfs,
554                          struct ntvfs_request *req, union smb_read *rd)
555 {
556         struct ipc_private *ipriv = talloc_get_type_abort(ntvfs->private_data,
557                                     struct ipc_private);
558         struct pipe_state *p;
559         struct ipc_read_state *state;
560         struct tevent_req *subreq;
561
562         if (rd->generic.level != RAW_READ_GENERIC) {
563                 return ntvfs_map_read(ntvfs, req, rd);
564         }
565
566         p = pipe_state_find(ipriv, rd->readx.in.file.ntvfs);
567         if (!p) {
568                 return NT_STATUS_INVALID_HANDLE;
569         }
570
571         state = talloc(req, struct ipc_read_state);
572         NT_STATUS_HAVE_NO_MEMORY(state);
573
574         state->ipriv = ipriv;
575         state->p = p;
576         state->req = req;
577         state->rd = rd;
578
579         /* rd->readx.out.data is already allocated */
580         ipc_readv_next_vector_init(&state->next_vector,
581                                    rd->readx.out.data,
582                                    rd->readx.in.maxcnt);
583
584         subreq = tstream_readv_pdu_queue_send(req,
585                                               ipriv->ntvfs->ctx->event_ctx,
586                                               p->npipe,
587                                               p->read_queue,
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);
592
593         req->async_states->state |= NTVFS_ASYNC_STATE_ASYNC;
594         return NT_STATUS_OK;
595 }
596
597 static void ipc_read_done(struct tevent_req *subreq)
598 {
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;
604         int ret;
605         int sys_errno;
606         NTSTATUS status;
607
608         ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
609         TALLOC_FREE(subreq);
610         if (ret == -1) {
611                 status = map_nt_error_from_unix_common(sys_errno);
612                 goto reply;
613         }
614
615         status = NT_STATUS_OK;
616         if (state->next_vector.remaining > 0) {
617                 status = STATUS_BUFFER_OVERFLOW;
618         }
619
620         rd->readx.out.remaining = state->next_vector.remaining;
621         rd->readx.out.compaction_mode = 0;
622         rd->readx.out.nread = ret;
623
624 reply:
625         req->async_states->status = status;
626         req->async_states->send_fn(req);
627 }
628
629 struct ipc_write_state {
630         struct ipc_private *ipriv;
631         struct pipe_state *p;
632         struct ntvfs_request *req;
633         union smb_write *wr;
634         struct iovec iov;
635 };
636
637 static void ipc_write_done(struct tevent_req *subreq);
638
639 /*
640   write to a file
641 */
642 static NTSTATUS ipc_write(struct ntvfs_module_context *ntvfs,
643                           struct ntvfs_request *req, union smb_write *wr)
644 {
645         struct ipc_private *ipriv = talloc_get_type_abort(ntvfs->private_data,
646                                     struct ipc_private);
647         struct pipe_state *p;
648         struct tevent_req *subreq;
649         struct ipc_write_state *state;
650
651         if (wr->generic.level != RAW_WRITE_GENERIC) {
652                 return ntvfs_map_write(ntvfs, req, wr);
653         }
654
655         p = pipe_state_find(ipriv, wr->writex.in.file.ntvfs);
656         if (!p) {
657                 return NT_STATUS_INVALID_HANDLE;
658         }
659
660         state = talloc(req, struct ipc_write_state);
661         NT_STATUS_HAVE_NO_MEMORY(state);
662
663         state->ipriv = ipriv;
664         state->p = p;
665         state->req = req;
666         state->wr = wr;
667         state->iov.iov_base = discard_const_p(void, wr->writex.in.data);
668         state->iov.iov_len = wr->writex.in.count;
669
670         subreq = tstream_writev_queue_send(state,
671                                            ipriv->ntvfs->ctx->event_ctx,
672                                            p->npipe,
673                                            p->write_queue,
674                                            &state->iov, 1);
675         NT_STATUS_HAVE_NO_MEMORY(subreq);
676         tevent_req_set_callback(subreq, ipc_write_done, state);
677
678         req->async_states->state |= NTVFS_ASYNC_STATE_ASYNC;
679         return NT_STATUS_OK;
680 }
681
682 static void ipc_write_done(struct tevent_req *subreq)
683 {
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;
689         int ret;
690         int sys_errno;
691         NTSTATUS status;
692
693         ret = tstream_writev_queue_recv(subreq, &sys_errno);
694         TALLOC_FREE(subreq);
695         if (ret == -1) {
696                 status = map_nt_error_from_unix_common(sys_errno);
697                 goto reply;
698         }
699
700         status = NT_STATUS_OK;
701
702         wr->writex.out.nwritten = ret;
703         wr->writex.out.remaining = 0;
704
705 reply:
706         req->async_states->status = status;
707         req->async_states->send_fn(req);
708 }
709
710 /*
711   seek in a file
712 */
713 static NTSTATUS ipc_seek(struct ntvfs_module_context *ntvfs,
714                          struct ntvfs_request *req,
715                          union smb_seek *io)
716 {
717         return NT_STATUS_ACCESS_DENIED;
718 }
719
720 /*
721   flush a file
722 */
723 static NTSTATUS ipc_flush(struct ntvfs_module_context *ntvfs,
724                           struct ntvfs_request *req,
725                           union smb_flush *io)
726 {
727         return NT_STATUS_ACCESS_DENIED;
728 }
729
730 /*
731   close a file
732 */
733 static NTSTATUS ipc_close(struct ntvfs_module_context *ntvfs,
734                           struct ntvfs_request *req, union smb_close *io)
735 {
736         struct ipc_private *ipriv = talloc_get_type_abort(ntvfs->private_data,
737                                     struct ipc_private);
738         struct pipe_state *p;
739
740         if (io->generic.level != RAW_CLOSE_GENERIC) {
741                 return ntvfs_map_close(ntvfs, req, io);
742         }
743
744         ZERO_STRUCT(io->generic.out);
745
746         p = pipe_state_find(ipriv, io->generic.in.file.ntvfs);
747         if (!p) {
748                 return NT_STATUS_INVALID_HANDLE;
749         }
750
751         talloc_free(p);
752
753         return NT_STATUS_OK;
754 }
755
756 /*
757   exit - closing files
758 */
759 static NTSTATUS ipc_exit(struct ntvfs_module_context *ntvfs,
760                          struct ntvfs_request *req)
761 {
762         struct ipc_private *ipriv = talloc_get_type_abort(ntvfs->private_data,
763                                     struct ipc_private);
764         struct pipe_state *p, *next;
765         
766         for (p=ipriv->pipe_list; p; p=next) {
767                 next = p->next;
768                 if (p->handle->session_info == req->session_info &&
769                     p->handle->smbpid == req->smbpid) {
770                         talloc_free(p);
771                 }
772         }
773
774         return NT_STATUS_OK;
775 }
776
777 /*
778   logoff - closing files open by the user
779 */
780 static NTSTATUS ipc_logoff(struct ntvfs_module_context *ntvfs,
781                            struct ntvfs_request *req)
782 {
783         struct ipc_private *ipriv = talloc_get_type_abort(ntvfs->private_data,
784                                     struct ipc_private);
785         struct pipe_state *p, *next;
786         
787         for (p=ipriv->pipe_list; p; p=next) {
788                 next = p->next;
789                 if (p->handle->session_info == req->session_info) {
790                         talloc_free(p);
791                 }
792         }
793
794         return NT_STATUS_OK;
795 }
796
797 /*
798   setup for an async call
799 */
800 static NTSTATUS ipc_async_setup(struct ntvfs_module_context *ntvfs,
801                                 struct ntvfs_request *req,
802                                 void *private_data)
803 {
804         return NT_STATUS_OK;
805 }
806
807 /*
808   cancel an async call
809 */
810 static NTSTATUS ipc_cancel(struct ntvfs_module_context *ntvfs,
811                            struct ntvfs_request *req)
812 {
813         return NT_STATUS_UNSUCCESSFUL;
814 }
815
816 /*
817   lock a byte range
818 */
819 static NTSTATUS ipc_lock(struct ntvfs_module_context *ntvfs,
820                          struct ntvfs_request *req, union smb_lock *lck)
821 {
822         return NT_STATUS_ACCESS_DENIED;
823 }
824
825 /*
826   set info on a open file
827 */
828 static NTSTATUS ipc_setfileinfo(struct ntvfs_module_context *ntvfs,
829                                 struct ntvfs_request *req, union smb_setfileinfo *info)
830 {
831         return NT_STATUS_ACCESS_DENIED;
832 }
833
834 /*
835   query info on a open file
836 */
837 static NTSTATUS ipc_qfileinfo(struct ntvfs_module_context *ntvfs,
838                               struct ntvfs_request *req, union smb_fileinfo *info)
839 {
840         struct ipc_private *ipriv = talloc_get_type_abort(ntvfs->private_data,
841                                     struct ipc_private);
842         struct pipe_state *p = pipe_state_find(ipriv, info->generic.in.file.ntvfs);
843         if (!p) {
844                 return NT_STATUS_INVALID_HANDLE;
845         }
846         switch (info->generic.level) {
847         case RAW_FILEINFO_GENERIC: 
848         {
849                 ZERO_STRUCT(info->generic.out);
850                 info->generic.out.attrib = FILE_ATTRIBUTE_NORMAL;
851                 info->generic.out.fname.s = strrchr(p->pipe_name, '\\');
852                 info->generic.out.alloc_size = 4096;
853                 info->generic.out.nlink = 1;
854                 /* What the heck?  Match Win2k3: IPC$ pipes are delete pending */
855                 info->generic.out.delete_pending = 1;
856                 return NT_STATUS_OK;
857         }
858         case RAW_FILEINFO_ALT_NAME_INFO:
859         case RAW_FILEINFO_ALT_NAME_INFORMATION:
860         case RAW_FILEINFO_STREAM_INFO:
861         case RAW_FILEINFO_STREAM_INFORMATION:
862         case RAW_FILEINFO_COMPRESSION_INFO:
863         case RAW_FILEINFO_COMPRESSION_INFORMATION:
864         case RAW_FILEINFO_NETWORK_OPEN_INFORMATION:
865         case RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION:
866                 return NT_STATUS_INVALID_PARAMETER;
867         case  RAW_FILEINFO_ALL_EAS:
868                 return NT_STATUS_ACCESS_DENIED;
869         default:
870                 return ntvfs_map_qfileinfo(ntvfs, req, info);
871         }
872 }
873
874
875 /*
876   return filesystem info
877 */
878 static NTSTATUS ipc_fsinfo(struct ntvfs_module_context *ntvfs,
879                            struct ntvfs_request *req, union smb_fsinfo *fs)
880 {
881         return NT_STATUS_ACCESS_DENIED;
882 }
883
884 /*
885   return print queue info
886 */
887 static NTSTATUS ipc_lpq(struct ntvfs_module_context *ntvfs,
888                         struct ntvfs_request *req, union smb_lpq *lpq)
889 {
890         return NT_STATUS_ACCESS_DENIED;
891 }
892
893 /* 
894    list files in a directory matching a wildcard pattern
895 */
896 static NTSTATUS ipc_search_first(struct ntvfs_module_context *ntvfs,
897                           struct ntvfs_request *req, union smb_search_first *io,
898                           void *search_private, 
899                           bool (*callback)(void *, const union smb_search_data *))
900 {
901         return NT_STATUS_ACCESS_DENIED;
902 }
903
904 /* 
905    continue listing files in a directory 
906 */
907 static NTSTATUS ipc_search_next(struct ntvfs_module_context *ntvfs,
908                          struct ntvfs_request *req, union smb_search_next *io,
909                          void *search_private, 
910                          bool (*callback)(void *, const union smb_search_data *))
911 {
912         return NT_STATUS_ACCESS_DENIED;
913 }
914
915 /* 
916    end listing files in a directory 
917 */
918 static NTSTATUS ipc_search_close(struct ntvfs_module_context *ntvfs,
919                           struct ntvfs_request *req, union smb_search_close *io)
920 {
921         return NT_STATUS_ACCESS_DENIED;
922 }
923
924 struct ipc_trans_state {
925         struct ipc_private *ipriv;
926         struct pipe_state *p;
927         struct ntvfs_request *req;
928         struct smb_trans2 *trans;
929         struct iovec writev_iov;
930         struct ipc_readv_next_vector_state next_vector;
931 };
932
933 static void ipc_trans_writev_done(struct tevent_req *subreq);
934 static void ipc_trans_readv_done(struct tevent_req *subreq);
935
936 /* SMBtrans - handle a DCERPC command */
937 static NTSTATUS ipc_dcerpc_cmd(struct ntvfs_module_context *ntvfs,
938                                struct ntvfs_request *req, struct smb_trans2 *trans)
939 {
940         struct ipc_private *ipriv = talloc_get_type_abort(ntvfs->private_data,
941                                     struct ipc_private);
942         struct pipe_state *p;
943         DATA_BLOB fnum_key;
944         uint16_t fnum;
945         struct ipc_trans_state *state;
946         struct tevent_req *subreq;
947
948         /*
949          * the fnum is in setup[1], a 16 bit value
950          * the setup[*] values are already in host byteorder
951          * but ntvfs_handle_search_by_wire_key() expects
952          * network byteorder
953          */
954         SSVAL(&fnum, 0, trans->in.setup[1]);
955         fnum_key = data_blob_const(&fnum, 2);
956
957         p = pipe_state_find_key(ipriv, req, &fnum_key);
958         if (!p) {
959                 return NT_STATUS_INVALID_HANDLE;
960         }
961
962         /*
963          * Trans requests are only allowed
964          * if no other Trans or Read is active
965          */
966         if (tevent_queue_length(p->read_queue) > 0) {
967                 return NT_STATUS_PIPE_BUSY;
968         }
969
970         state = talloc(req, struct ipc_trans_state);
971         NT_STATUS_HAVE_NO_MEMORY(state);
972
973         trans->out.setup_count = 0;
974         trans->out.setup = NULL;
975         trans->out.params = data_blob(NULL, 0);
976         trans->out.data = data_blob_talloc(req, NULL, trans->in.max_data);
977         NT_STATUS_HAVE_NO_MEMORY(trans->out.data.data);
978
979         state->ipriv = ipriv;
980         state->p = p;
981         state->req = req;
982         state->trans = trans;
983         state->writev_iov.iov_base = (char *) trans->in.data.data;
984         state->writev_iov.iov_len = trans->in.data.length;
985
986         ipc_readv_next_vector_init(&state->next_vector,
987                                    trans->out.data.data,
988                                    trans->out.data.length);
989
990         subreq = tstream_writev_queue_send(state,
991                                            ipriv->ntvfs->ctx->event_ctx,
992                                            p->npipe,
993                                            p->write_queue,
994                                            &state->writev_iov, 1);
995         NT_STATUS_HAVE_NO_MEMORY(subreq);
996         tevent_req_set_callback(subreq, ipc_trans_writev_done, state);
997
998         req->async_states->state |= NTVFS_ASYNC_STATE_ASYNC;
999         return NT_STATUS_OK;
1000 }
1001
1002 static void ipc_trans_writev_done(struct tevent_req *subreq)
1003 {
1004         struct ipc_trans_state *state =
1005                 tevent_req_callback_data(subreq,
1006                 struct ipc_trans_state);
1007         struct ipc_private *ipriv = state->ipriv;
1008         struct pipe_state *p = state->p;
1009         struct ntvfs_request *req = state->req;
1010         int ret;
1011         int sys_errno;
1012         NTSTATUS status;
1013
1014         ret = tstream_writev_queue_recv(subreq, &sys_errno);
1015         TALLOC_FREE(subreq);
1016         if (ret == 0) {
1017                 status = NT_STATUS_PIPE_DISCONNECTED;
1018                 goto reply;
1019         } else if (ret == -1) {
1020                 status = map_nt_error_from_unix_common(sys_errno);
1021                 goto reply;
1022         }
1023
1024         subreq = tstream_readv_pdu_queue_send(state,
1025                                               ipriv->ntvfs->ctx->event_ctx,
1026                                               p->npipe,
1027                                               p->read_queue,
1028                                               ipc_readv_next_vector,
1029                                               &state->next_vector);
1030         if (!subreq) {
1031                 status = NT_STATUS_NO_MEMORY;
1032                 goto reply;
1033         }
1034         tevent_req_set_callback(subreq, ipc_trans_readv_done, state);
1035         return;
1036
1037 reply:
1038         req->async_states->status = status;
1039         req->async_states->send_fn(req);
1040 }
1041
1042 static void ipc_trans_readv_done(struct tevent_req *subreq)
1043 {
1044         struct ipc_trans_state *state =
1045                 tevent_req_callback_data(subreq,
1046                 struct ipc_trans_state);
1047         struct ntvfs_request *req = state->req;
1048         struct smb_trans2 *trans = state->trans;
1049         int ret;
1050         int sys_errno;
1051         NTSTATUS status;
1052
1053         ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
1054         TALLOC_FREE(subreq);
1055         if (ret == -1) {
1056                 status = map_nt_error_from_unix_common(sys_errno);
1057                 goto reply;
1058         }
1059
1060         status = NT_STATUS_OK;
1061         if (state->next_vector.remaining > 0) {
1062                 status = STATUS_BUFFER_OVERFLOW;
1063         }
1064
1065         trans->out.data.length = ret;
1066
1067 reply:
1068         req->async_states->status = status;
1069         req->async_states->send_fn(req);
1070 }
1071
1072 /* SMBtrans - set named pipe state */
1073 static NTSTATUS ipc_set_nm_pipe_state(struct ntvfs_module_context *ntvfs,
1074                                       struct ntvfs_request *req, struct smb_trans2 *trans)
1075 {
1076         struct ipc_private *ipriv = talloc_get_type_abort(ntvfs->private_data,
1077                                     struct ipc_private);
1078         struct pipe_state *p;
1079         DATA_BLOB fnum_key;
1080
1081         /* the fnum is in setup[1] */
1082         fnum_key = data_blob_const(&trans->in.setup[1], sizeof(trans->in.setup[1]));
1083
1084         p = pipe_state_find_key(ipriv, req, &fnum_key);
1085         if (!p) {
1086                 return NT_STATUS_INVALID_HANDLE;
1087         }
1088
1089         if (trans->in.params.length != 2) {
1090                 return NT_STATUS_INVALID_PARAMETER;
1091         }
1092
1093         /*
1094          * TODO: pass this to the tstream_npa logic
1095          */
1096         p->device_state = SVAL(trans->in.params.data, 0);
1097
1098         trans->out.setup_count = 0;
1099         trans->out.setup = NULL;
1100         trans->out.params = data_blob(NULL, 0);
1101         trans->out.data = data_blob(NULL, 0);
1102
1103         return NT_STATUS_OK;
1104 }
1105
1106
1107 /* SMBtrans - used to provide access to SMB pipes */
1108 static NTSTATUS ipc_trans(struct ntvfs_module_context *ntvfs,
1109                                 struct ntvfs_request *req, struct smb_trans2 *trans)
1110 {
1111         NTSTATUS status;
1112
1113         if (strequal(trans->in.trans_name, "\\PIPE\\LANMAN"))
1114                 return ipc_rap_call(req, ntvfs->ctx->event_ctx, ntvfs->ctx->lp_ctx, trans);
1115
1116         if (trans->in.setup_count != 2) {
1117                 return NT_STATUS_INVALID_PARAMETER;
1118         }
1119
1120         switch (trans->in.setup[0]) {
1121         case TRANSACT_SETNAMEDPIPEHANDLESTATE:
1122                 status = ipc_set_nm_pipe_state(ntvfs, req, trans);
1123                 break;
1124         case TRANSACT_DCERPCCMD:
1125                 status = ipc_dcerpc_cmd(ntvfs, req, trans);
1126                 break;
1127         default:
1128                 status = NT_STATUS_INVALID_PARAMETER;
1129                 break;
1130         }
1131
1132         return status;
1133 }
1134
1135 struct ipc_ioctl_state {
1136         struct ipc_private *ipriv;
1137         struct pipe_state *p;
1138         struct ntvfs_request *req;
1139         union smb_ioctl *io;
1140         struct iovec writev_iov;
1141         struct ipc_readv_next_vector_state next_vector;
1142 };
1143
1144 static void ipc_ioctl_writev_done(struct tevent_req *subreq);
1145 static void ipc_ioctl_readv_done(struct tevent_req *subreq);
1146
1147 static NTSTATUS ipc_ioctl_smb2(struct ntvfs_module_context *ntvfs,
1148                                struct ntvfs_request *req, union smb_ioctl *io)
1149 {
1150         struct ipc_private *ipriv = talloc_get_type_abort(ntvfs->private_data,
1151                                     struct ipc_private);
1152         struct pipe_state *p;
1153         struct ipc_ioctl_state *state;
1154         struct tevent_req *subreq;
1155
1156         switch (io->smb2.in.function) {
1157         case FSCTL_NAMED_PIPE_READ_WRITE:
1158                 break;
1159
1160         default:
1161                 return NT_STATUS_FS_DRIVER_REQUIRED;
1162         }
1163
1164         p = pipe_state_find(ipriv, io->smb2.in.file.ntvfs);
1165         if (!p) {
1166                 return NT_STATUS_INVALID_HANDLE;
1167         }
1168
1169         /*
1170          * Trans requests are only allowed
1171          * if no other Trans or Read is active
1172          */
1173         if (tevent_queue_length(p->read_queue) > 0) {
1174                 return NT_STATUS_PIPE_BUSY;
1175         }
1176
1177         state = talloc(req, struct ipc_ioctl_state);
1178         NT_STATUS_HAVE_NO_MEMORY(state);
1179
1180         io->smb2.out.reserved   = 0;
1181         io->smb2.out.function   = io->smb2.in.function;
1182         io->smb2.out.flags      = 0;
1183         io->smb2.out.reserved2  = 0;
1184         io->smb2.out.in         = data_blob_null;
1185         io->smb2.out.out = data_blob_talloc(req, NULL, io->smb2.in.max_output_response);
1186         NT_STATUS_HAVE_NO_MEMORY(io->smb2.out.out.data);
1187
1188         state->ipriv = ipriv;
1189         state->p = p;
1190         state->req = req;
1191         state->io = io;
1192         state->writev_iov.iov_base = (char *) io->smb2.in.out.data;
1193         state->writev_iov.iov_len = io->smb2.in.out.length;
1194
1195         ipc_readv_next_vector_init(&state->next_vector,
1196                                    io->smb2.out.out.data,
1197                                    io->smb2.out.out.length);
1198
1199         subreq = tstream_writev_queue_send(state,
1200                                            ipriv->ntvfs->ctx->event_ctx,
1201                                            p->npipe,
1202                                            p->write_queue,
1203                                            &state->writev_iov, 1);
1204         NT_STATUS_HAVE_NO_MEMORY(subreq);
1205         tevent_req_set_callback(subreq, ipc_ioctl_writev_done, state);
1206
1207         req->async_states->state |= NTVFS_ASYNC_STATE_ASYNC;
1208         return NT_STATUS_OK;
1209 }
1210
1211 static void ipc_ioctl_writev_done(struct tevent_req *subreq)
1212 {
1213         struct ipc_ioctl_state *state =
1214                 tevent_req_callback_data(subreq,
1215                 struct ipc_ioctl_state);
1216         struct ipc_private *ipriv = state->ipriv;
1217         struct pipe_state *p = state->p;
1218         struct ntvfs_request *req = state->req;
1219         int ret;
1220         int sys_errno;
1221         NTSTATUS status;
1222
1223         ret = tstream_writev_queue_recv(subreq, &sys_errno);
1224         TALLOC_FREE(subreq);
1225         if (ret == -1) {
1226                 status = map_nt_error_from_unix_common(sys_errno);
1227                 goto reply;
1228         }
1229
1230         subreq = tstream_readv_pdu_queue_send(state,
1231                                               ipriv->ntvfs->ctx->event_ctx,
1232                                               p->npipe,
1233                                               p->read_queue,
1234                                               ipc_readv_next_vector,
1235                                               &state->next_vector);
1236         if (!subreq) {
1237                 status = NT_STATUS_NO_MEMORY;
1238                 goto reply;
1239         }
1240         tevent_req_set_callback(subreq, ipc_ioctl_readv_done, state);
1241         return;
1242
1243 reply:
1244         req->async_states->status = status;
1245         req->async_states->send_fn(req);
1246 }
1247
1248 static void ipc_ioctl_readv_done(struct tevent_req *subreq)
1249 {
1250         struct ipc_ioctl_state *state =
1251                 tevent_req_callback_data(subreq,
1252                 struct ipc_ioctl_state);
1253         struct ntvfs_request *req = state->req;
1254         union smb_ioctl *io = state->io;
1255         int ret;
1256         int sys_errno;
1257         NTSTATUS status;
1258
1259         ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
1260         TALLOC_FREE(subreq);
1261         if (ret == -1) {
1262                 status = map_nt_error_from_unix_common(sys_errno);
1263                 goto reply;
1264         }
1265
1266         status = NT_STATUS_OK;
1267         if (state->next_vector.remaining > 0) {
1268                 status = STATUS_BUFFER_OVERFLOW;
1269         }
1270
1271         io->smb2.out.out.length = ret;
1272
1273 reply:
1274         req->async_states->status = status;
1275         req->async_states->send_fn(req);
1276 }
1277
1278 /*
1279   ioctl interface
1280 */
1281 static NTSTATUS ipc_ioctl(struct ntvfs_module_context *ntvfs,
1282                           struct ntvfs_request *req, union smb_ioctl *io)
1283 {
1284         switch (io->generic.level) {
1285         case RAW_IOCTL_SMB2:
1286                 return ipc_ioctl_smb2(ntvfs, req, io);
1287
1288         case RAW_IOCTL_SMB2_NO_HANDLE:
1289                 return NT_STATUS_FS_DRIVER_REQUIRED;
1290
1291         default:
1292                 return NT_STATUS_ACCESS_DENIED;
1293         }
1294 }
1295
1296
1297 /*
1298   initialialise the IPC backend, registering ourselves with the ntvfs subsystem
1299  */
1300 NTSTATUS ntvfs_ipc_init(TALLOC_CTX *ctx)
1301 {
1302         NTSTATUS ret;
1303         struct ntvfs_ops ops;
1304         NTVFS_CURRENT_CRITICAL_SIZES(vers);
1305
1306         ZERO_STRUCT(ops);
1307         
1308         /* fill in the name and type */
1309         ops.name = "default";
1310         ops.type = NTVFS_IPC;
1311
1312         /* fill in all the operations */
1313         ops.connect_fn = ipc_connect;
1314         ops.disconnect_fn = ipc_disconnect;
1315         ops.unlink_fn = ipc_unlink;
1316         ops.chkpath_fn = ipc_chkpath;
1317         ops.qpathinfo_fn = ipc_qpathinfo;
1318         ops.setpathinfo_fn = ipc_setpathinfo;
1319         ops.open_fn = ipc_open;
1320         ops.mkdir_fn = ipc_mkdir;
1321         ops.rmdir_fn = ipc_rmdir;
1322         ops.rename_fn = ipc_rename;
1323         ops.copy_fn = ipc_copy;
1324         ops.ioctl_fn = ipc_ioctl;
1325         ops.read_fn = ipc_read;
1326         ops.write_fn = ipc_write;
1327         ops.seek_fn = ipc_seek;
1328         ops.flush_fn = ipc_flush;
1329         ops.close_fn = ipc_close;
1330         ops.exit_fn = ipc_exit;
1331         ops.lock_fn = ipc_lock;
1332         ops.setfileinfo_fn = ipc_setfileinfo;
1333         ops.qfileinfo_fn = ipc_qfileinfo;
1334         ops.fsinfo_fn = ipc_fsinfo;
1335         ops.lpq_fn = ipc_lpq;
1336         ops.search_first_fn = ipc_search_first;
1337         ops.search_next_fn = ipc_search_next;
1338         ops.search_close_fn = ipc_search_close;
1339         ops.trans_fn = ipc_trans;
1340         ops.logoff_fn = ipc_logoff;
1341         ops.async_setup_fn = ipc_async_setup;
1342         ops.cancel_fn = ipc_cancel;
1343
1344         /* register ourselves with the NTVFS subsystem. */
1345         ret = ntvfs_register(&ops, &vers);
1346
1347         if (!NT_STATUS_IS_OK(ret)) {
1348                 DEBUG(0,("Failed to register IPC backend!\n"));
1349                 return ret;
1350         }
1351
1352         return ret;
1353 }